現代医学におけるデータサイエンスの役割は何ですか?

美容とファッションにおけるデータサイエンスの重要性とは?

イントロダクション

AIの台頭により、働くプロフェッショナルの生活を簡素化するために、データに基づいた意思決定にますます頼るようになりました。サプライチェーンの物流や顧客へのローンの承認など、データは鍵を握っています。データサイエンスの力を医療の分野に活用することで、画期的な成果をもたらすことができます。データサイエンティストが現代医学の膨大な量のデータを分析することで、発見や治療につながるパターンを見つけ出すことができます。医療業界を革命化する可能性を秘めているデータサイエンスを医療領域に統合することは、単なる良い考えだけでなく、必要不可欠です。

データ前処理

いくつかの列をクリーンアップしましょう。前のステップで、すべての列が整数であるとわかりました。そのため、まず、年齢、用量、期間を数値に変換します。同様に、データ入力の日付を日時型に変換します。直接変換する代わりに、新しい列を作成します。つまり、Age 列の数値バージョンAge2 列を作成します。

df['Age2'] = pd.to_numeric(df['Age'],errors='coerce')df['Dosage (gram)2'] = pd.to_numeric(df['Dosage (gram)'],errors='coerce')df['Duration (days)2'] = pd.to_numeric(df['Duration (days)'],errors='coerce')df['Date of Data Entry2'] = pd.to_datetime(df['Date of Data Entry'],errors='coerce')df.info()

出力:

<class 'pandas.core.frame.DataFrame'>RangeIndex: 833 entries, 0 to 832Data columns (total 14 columns): #   Column               Non-Null Count  Dtype         ---  ------               --------------  -----          0   Age                  833 non-null    object         1   Date of Data Entry   833 non-null    object         2   Gender               833 non-null    object         3   Diagnosis            833 non-null    object         4   Name of Drug         833 non-null    object         5   Dosage (gram)        833 non-null    object         6   Route                833 non-null    object         7   Frequency            833 non-null    object         8   Duration (days)      833 non-null    object         9   Indication           832 non-null    object         10  Age2                 832 non-null    float64        11  Dosage (gram)2       831 non-null    float64        12  Duration (days)2     831 non-null    float64        13  Date of Data Entry2  831 non-null    datetime64[ns]dtypes: datetime64[ns](1), float64(3), object(10)memory usage: 91.2+ KB

変換後、いくつかのヌル値が存在することがわかります。それらのデータを確認しましょう。

df[(df['Dosage (gram)2'].isnull())  | (df['Duration (days)2'].isnull())  | (df['Age2'].isnull())  | (df['Date of Data Entry2'].isnull())  ]#import csv

出力:

データセットにゴミ値が含まれているようです。これを削除しましょう。

今度は、新しい列の値を古い列に代入し、新しく作成した列を削除します。

df = df[~((df['Dosage (gram)2'].isnull())  | (df['Duration (days)2'].isnull())  | (df['Age2'].isnull())  | (df['Date of Data Entry2'].isnull()))  ]df['Age'] = df['Age2'].astype('int')df['Dosage (gram)'] = df['Dosage (gram)2']df['Date of Data Entry'] = df['Date of Data Entry2']df['Duration (days)'] = df['Duration (days)2'].astype('int')df = df.drop(['Age2','Dosage (gram)2','Date of Data Entry2','Duration (days)2'],axis=1)print(df.shape)df.head()

出力:

いくつかの統計を見てみましょう

今、すべての列にわたるいくつかの統計を見てみましょう。describe関数を使用し、include引数を渡してすべての列に対する統計値を取得します。それを調べてみましょう

df.describe(include='all')

出力:

観察結果:

  • 年齢は1で、最大値は90です。
  • データ入力の列を見ると、19-Dec-2019の1時から7時までのデータを含んでいることがわかります。
  • 性別は2つの異なる値があります。
  • 用量は0.02グラムから960グラムの最大値を持っています(極端な値のようです)。
  • 期間は1の値を持ち、最大値は28日です。
  • 診断、薬の名前、経路、頻度、および指示の列には異なる値があります。これらを調べましょう。

単変量EDA 経路と頻度の列

ここでは、経路と頻度の列を調べてみます。value_counts()関数を使用します。

display(df['Route'].value_counts())print()df['Frequency'].value_counts()

出力:

RouteIV      534Oral    293IM        4Name: count, dtype: int64FrequencyBD     430TDS    283OD     110QID      8Name: count, dtype: int64

観察結果:

  • 薬の治療の経路は3つあります。最も使用されている経路はIVで、最も使用されているのはIMです。
  • 薬の治療の頻度は4つあります。最も使用されている頻度はBDで、最も使用されているのはQIDです。

単変量EDA 診断の列

ここでは、診断の列を調べます。value_counts()関数を使用します。

df['Diagnosis'].value_counts()

出力:

上記のコードを実行すると、263の異なる値があることがわかります。また、各患者には複数の診断があることがわかります(カンマで区切られています)。この列についてより理解するために、ワードクラウドを作成して不要なノイズをフィルタリングするためのストップワードを除去してみましょう。

text = " ".join(diagnosis for diagnosis in adf.Diagnosis)print ("組み合わせの全診断には{}個の単語があります。".format(len(text)))stopwords = set(STOPWORDS)# ワードクラウドイメージを生成するwordcloud = WordCloud(stopwords=stopwords, background_color="white").generate(text)# 生成されたイメージを表示する:# matplotlibの方法:plt.imshow(wordcloud, interpolation='bilinear')plt.axis("off")plt.show()

出力:

組み合わせの全診断には35359個の単語があります。

観察結果:

  • 組み合わせの全診断には35359個の単語があります。多くの単語が繰り返されます。
  • ワードクラウドを見ると、胸部感染症やコッホ肺などがより頻繁に診断されているようです。
  • 糖尿病や髄膜腫などの他の状態も見ることができます。

上位と下位の10個の単語/フレーズを見てみましょう。collectionsライブラリ内のCounter関数を使用します。

A = collections.Counter([i.strip().lower()   for i in text.split(',') if (i.strip().lower()) not in stopwords ])print('Top 10 words/phrases')display(A.most_common(10))print('\nBottom 10 words/phrases')display(A.most_common()[-11:-1])

出力:

トップ10の単語/フレーズ[('col', 77), ('chest infection', 68), ('ihd', 55), ('copd', 40), ('hypertension', 38), ('ccf', 36), ('type 2 dm', 32), ("koch's lung", 28), ('ckd', 28), ('uraemic gastritis', 18)]ボトム10の単語/フレーズ[('poorly controlled dm complicated uti', 1), ('poorly controlled dm septic shock', 1), ('hypertension hepatitis', 1), ('uti hepatitis', 1), ('uti uti', 1), ('cff ppt by chest infection early col', 1), ('operated spinal cord', 1), ('hematoma and paraplegia he', 1), ('rvi with col glandular fever', 1), ('fever with confusion ccf', 1)]

観察:

  • トップ10の単語/フレーズの中で、colchest infectionが最も頻出しています。77人がcolと診断され、68人がchest infectionと診断されました。
  • ボトム10の単語/フレーズの中では、リストされているものがそれぞれ1回しか起こらないことがわかります。

単変量 EDA インディケーション列

ここでは、インディケーション列を調査します。value_counts()関数を使用します。

df['Indication'].value_counts()を表示print()df['Indication'].value_counts(1)

出力:

Indicationchest infection            92col                        32uti                        30type 2 dm                  25prevention of infection    22                           ..pad(lt u.l)                 1old stroke                  1fainting attack             1cheat infection             1centepede bite              1Name: count, Length: 220, dtype: int64Indicationchest infection            0.110843col                        0.038554uti                        0.036145type 2 dm                  0.030120prevention of infection    0.026506                             ...   pad(lt u.l)                0.001205old stroke                 0.001205fainting attack            0.001205cheat infection            0.001205centepede bite             0.001205Name: proportion, Length: 220, dtype: float64

このインディケーション列には220の値があります。chess(チェス)とcheat(チート)のようなスペルの間違いも頻出しているようです。同じ単語をクリーンアップできます。現在の練習では、上位25%のインディケーションを考慮してみましょう。

top_indications = df['Indication'].value_counts(1).reset_index()top_indications['cum_proportion'] = top_indications['proportion'].cumsum()top_indications = top_indications[top_indications['cum_proportion']<0.25]top_indications

出力:

このデータフレームは、後の二変量分析およびモデリングの演習で使用します。

単変量 EDA 医薬品名列

ここでは、この列を調査します。value_counts()関数を使用します。

df['Name of Drug'].nunique()を表示df['Name of Drug'].value_counts()を表示

出力:

55Name of Drugceftriaxone                    221co-amoxiclav                   162metronidazole                   59cefixime                        58septrin                         37clarithromycin                  32levofloxacin                    31amoxicillin+flucloxacillin      29ceftazidime                     24cefepime                        14cefipime                        13clindamycin                     12rifaximin                       10amikacin                         9cefoperazone                     9coamoxiclav                      9meropenem                        8ciprofloxacin                    7gentamicin                 ...

観察結果:

  • ユニークな薬剤は55種類あります。
  • 再び、スペルの間違いが見られます – ceftriaxone vs ceftiaxone。ユニークな薬剤の数は低くなる可能性があります。

ここで上位5つの薬剤を考えましょう。各薬剤が寄与している累積割合を保存するためのカラム「cum_proportion」を作成します。

top_drugs = (df['Name of Drug'].value_counts(1).reset_index())top_drugs['cum_proportion'] = top_drugs['proportion'].cumsum()top_drugs = top_drugs.head()top_drugs

出力結果:

上位5つの薬剤は、患者の64.6%に与えられています。

注意:スペルの間違いを修正すれば、64.6%よりも高くなる可能性があります。

このデータフレームは、後に二変量分析とモデリングの演習で使用します。

二変量分析:適応症 vs 薬剤名

ここでは、先ほど作成したtop_indicationsとtop_drugsのデータフレームを考慮して、それらの分布を見てみましょう。つまり、上位5つの薬剤名 vs 上位25%の適応症を比較します。pivot_table()関数を使用します。

(df[(df['Indication'].isin(top_indications['Indication']))   &(df['Name of Drug'].isin(top_drugs['Name of Drug']))].pivot_table(index='Indication',columns='Name of Drug',values='Age',aggfunc='count'))

出力結果:

観察結果:

  • 胸部感染症には、最も推奨される薬剤はコアモキシクラブであり、次にセフトリアクソンがあります。
  • 他の適応症についても同様の観察ができます。

注意:これらの薬剤は、患者の年齢、性別、診断、および病歴など、他の要素に基づいて処方されます。

二変量分析:適応症 vs 年齢

ここでは、年配の患者に特定の状態が現れるかどうかを理解しようとします。top_indicationsを考慮し、年齢の平均値と中央値を調べます。

(df[df['Indication'].isin(top_indications['Indication'])].groupby('Indication')['Age'].agg(['mean','median','count']))

出力結果:

観察結果:

  • 適応症 – 胸部感染症感染症の予防は、若い患者でより頻繁に観察されます。
  • 尿路感染症中年の患者で観察されます。
  • 適応症: 胸部感染症2型糖尿病は、年配の患者でより頻繁に観察されます。

二変量分析:薬剤名 vs 年齢

ここでは、特定の薬剤が年配の患者に使用されているかどうかを理解しようとします。 top_drugsを考慮し、年齢の平均値と中央値を調べます。

(df[df['Name of Drug'].isin(top_drugs['Name of Drug'])].groupby('Name of Drug')['Age'].agg(['mean','median','count']).sort_values(by='median'))

出力結果:

観察結果:

  1. セプトリンセフィキシム若い患者に処方されます。
  2. セフトリアクソン中年患者に処方されます。
  3. メトロニダゾールコアモキシクラブ年配の患者に処方されます。

モデリング手法

ここでは、薬剤師や処方医を支援しようとします。問題は、診断、年齢、性別の列に基づいてどの薬剤が患者に与えられるかを特定することです。

いくつかの考慮事項と仮定:

  1. この演習では、上位5つの薬物のみを考慮し、残りを「その他」としてマークします。
  2. したがって、(診断、年齢、性別)の各値について、推奨される薬物を特定することが目的です。ベースラインモデルは(1/6)= 16.67%の正確さです。

それを上回ることができるか見てみましょう。モデリングの練習のために、データフレームのコピーを作成します。

adf = df.copy()adf['Output'] = np.where(df['Name of Drug'].isin(top_drugs['Name of Drug']),                    df['Name of Drug'],'その他')adf['Output'].value_counts()

出力:

その他             294ceftriaxone      221co-amoxiclav     162metronidazole     59cefixime          58septrin           37Name: count, dtype: int64

この分布は以前にも見ました。クラスが均等に分布していないことを意味します。モデルを初期化する際にはこれを考慮に入れる必要があります。

特徴エンジニアリング

診断カラムのより頻繁な単語/ n-gramをキャプチャしようとします。Count Vectorizerモジュールを使用します。

vectorizer = CountVectorizer(max_features=150,stop_words='english',              ngram_range=(1,3))X = vectorizer.fit_transform(adf['Diagnosis'].str.lower())vectorizer.get_feature_names_out()

出力:

array(['膿瘍', '急性', '急性感染性胃腸炎', '心房細動', '急性腎障害', '急性腎障害, 慢性腎臓病',       '急性腎障害, 慢性腎臓病, 逆行性', 'アルコール性', '貧血', '人工股関節', '咬傷', '出血',       '骨', 'がん', '肺炎', '心臓衰弱', '心臓衰弱, 肺炎',       '心臓衰弱, 肺炎, 胸部感染症', '心臓衰弱, 肝機能障害上昇', '心臓腎臓病変', '心臓腎臓病変, 肺炎',       '脳', '脳梗塞', '胸部', '胸部感染症',       '胸部感染症, 前立腺がん', '慢性', '腎臓病', '腎臓病, 胸部感染症',       '逆行性', '大腸', '大腸, ポータル圧迫',       '大腸, ポータル圧迫, 喘息', '呼吸器疾患',       '呼吸器疾患, 胸部感染症', '虚弱',       '虚弱, 過剰嘔吐', '虚弱, 過剰嘔吐, 糖尿病', '糖尿病',       '疾患', '疾患, 腎臓障害', '疾患, 腎臓障害, 障害', '虚血性脳疾患',       '虚血性脳疾患, 心臓病', '肺',       '肺炎', '肺炎, 呼吸器疾患',       '肺炎, 呼吸器疾患, 胸部感染症', '骨髄', '多発',       '多発性骨髄腫', '多発性骨髄腫, 腎臓病', '骨髄腫',       '骨髄腫, 腎臓病', '新規', '既往', '胸膜', '胸膜滲出液',       '肺炎', 'ポータル圧迫', 'ポータル圧迫',       '前立腺がん', '糖尿病',       '糖尿病, 心臓病', '糖尿病, 心臓病, 心臓疾患', '尿毒症', '尿毒症, 糖尿病',       '尿毒症, 糖尿病, 胃腸炎', '胃腸炎',       '胃腸炎, 肝炎', '胃腸炎, 肝炎, 腎障害', '胆嚢',       '胆嚢, 胆石症', '胆嚢, 胆石症, 胆嚢炎',       '肝臓疾患', '高血圧',       '高血圧, 腎臓病', '高血圧, 腎臓病, 高血圧病', '虚血性心疾患',       '障害', '障害, USB噛傷', '進行中', '進行中, 高血圧病',       '進行中, 高血圧病, 心臓病', '脳卒中', '結核', 'タイプ', 'タイプ2糖尿病',       'タイプ2糖尿病, 心臓病', '尿毒症', '尿毒症, タイプ2糖尿病',       '尿毒症, タイプ2糖尿病, 胃腸炎', '過剰嘔吐', '過剰嘔吐, 尿毒症',       '過剰嘔吐, 尿毒症, 胃腸炎'],      dtype=object)

上記のリストは、ストップワードを削除した後の診断列で観察されたトップ150のNグラムを紹介しています。

データセットの作成

ここでは、作成した特徴量と年齢・性別の列を入力として含む単一のデータフレームを作成します。Drug Namesを数値に変換するためにLabel Encoderを使用します。

feature_df = pd.DataFrame(X.toarray(),columns=vectorizer.get_feature_names_out())feature_df['Age'] = adf['Age'].fillna(0).astype('int')feature_df['Gender_Male'] = np.where(adf['Gender']=='Male',1,0)le = LabelEncoder()feature_df['Output'] = le.fit_transform(adf['Output'])

さて、トレーニングセットとテストセットに分割します。データの20%をテストセットとして保持します。再現性を確保するためにrandom_state引数を使用します。

X_train, X_test, y_train, y_test = train_test_split(  feature_df.drop('Output',axis=1).fillna(-1),   feature_df['Output'],   test_size=0.2, random_state=42)

モデリング

ここでは、ランダムフォレストモデルを使用しました。他のモデルでも試すことができます。クラスの分布が均等でないことが以前にわかっているため、class_weightパラメータを使用します。

clf = RandomForestClassifier(max_depth=6, random_state=0,   class_weight='balanced')clf.fit(X_train, y_train)

トレーニングデータセットの正確さとその他のメトリクスを見てみましょう。

# accuracy on X_train datafinal_accuracy = clf.score(X_train, y_train)print("final_accuracy is : ",final_accuracy)# creating a confusion matrix for determining and visualizing the accuracy scoreclf_predict = clf.predict(X_train)print(classification_report(y_train, clf_predict,target_names=list(mapping_df['Actual_Name'])))

出力:

final_accuracy is :  0.411144578313253               precision    recall  f1-score   support        Other       0.84      0.30      0.44       236     cefixime       0.16      0.86      0.27        49  ceftriaxone       0.74      0.26      0.39       176 co-amoxiclav       0.48      0.47      0.48       127metronidazole       0.39      0.59      0.47        49      septrin       0.45      0.93      0.61        27     accuracy                           0.41       664    macro avg       0.51      0.57      0.44       664 weighted avg       0.64      0.41      0.43       664

同様に、テストデータセットの正確さとその他のメトリクスを見てみましょう。

# accuracy on X_test datafinal_accuracy = clf.score(X_test, y_test)print("final_accuracy is : ",final_accuracy)# creating a confusion matrix for determining and visualizing the accuracy scoreclf_predict = clf.predict(X_test)print(classification_report(y_test, clf_predict,target_names=list(mapping_df['Actual_Name'])))

出力:

final_accuracy is :  0.38323353293413176               precision    recall  f1-score   support        Other       0.71      0.38      0.49        58     cefixime       0.08      0.56      0.14         9  ceftriaxone       0.36      0.09      0.14        45 co-amoxiclav       0.64      0.71      0.68        35metronidazole       0.31      0.40      0.35        10      septrin       0.44      0.40      0.42        10     accuracy                           0.38       167    macro avg       0.42      0.42      0.37       167 weighted avg       0.53      0.38      0.41       167

主な観察結果:

  • モデルは、トレーニングデータで41.11%、テストデータで38.32%の正確さを示しています。
  • f1スコアを見ると、その他の薬剤名の場合、トレーニングデータセットでは0.44、テストデータセットでは0.49の値が観察されました。
  • また、セフィキシムセフトリアキソンのテストのf1スコアが低いこともわかります。セフィキシムはサンプル数が9つしかなく、セフトリアキソンは45のサンプルがあります。したがって、これらのデータポイントを分析して、フィーチャーセットの改善の余地を理解する必要があります。

結論

この記事では、医療データセットを終始分析しました。その後、データセットをクリーニングしました。基本統計、分布、ワードクラウドを使用して列を理解しました。それから、診断、年齢、性別の列に基づいて患者にどの薬剤を服用させるかを薬剤師や処方医師が助けるために問題文を作成しました。

主なハイライト

  • モデリングの練習のために、診断の列から上位150の単語/バイグラム/トリグラムを考慮しました。つまり、診断の列を分割して150の特徴量を作成しました。
  • また、年齢と性別の特徴も考慮しました。合計で152の特徴を持っています。
  • これらの152の特徴を使用して、どの薬剤/薬品が処方されるかを判断しました。
  • ベースライン/ランダムモデルは16.67%の正確さでした。私たちのモデルは、トレーニングデータで41.11%、テストデータで38.32%の正確さを示しています。これはベースラインモデルよりもかなり改善された結果です。

モデルのパフォーマンスを向上させるために試してみること:

  1. TF-IDFや埋め込みを使用して特徴量を抽出する。
  2. 異なるモデルを試し、グリッドサーチと交差検証を使用して正確性を最適化する。
  3. より多くの薬剤を予測してみる。

私の記事を読んでいただきありがとうございます。この件について議論するために、リンクトインで私とつながって気軽に連絡してください。

この記事で表示されているメディアはAnalytics Vidhyaの所有ではなく、著者の独自の判断に基づいて使用されています。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more