Pandas를 이용한 데이터 분석 - 2
Pandas를 이용한 데이터 분석 - 2
안녕하세요 @oscarpark 입니다.
지난 포스팅 Pandas를 이용한 데이터 분석 - 1 에서는 Pandas 모듈을 이용해 TCGA (The Cancer Genome Atlas)에서 제공하는 대장암 환자의 임상 데이터를 불러들여 원하는 columns만 slicing하고 결측치 값 (missing values)을 뺀 후 scatter matrix로 변수들의 분포와 흩어진 정도를 살펴봤습니다.
이번 포스팅에서는 column 단위로 계산하는 방법과 시각화를 통해 원하는 데이터를 보이는 법에 대해 다뤄보겠습니다.
Column 단위 계산 계산
BMI 계산
체질량 지수 (BMI; Body Mess Index 또는 Quetelet index)는 체중과 키의 관계로 조직 (tissue; fat, muscle, and bone)을 양적으로 나타내는 것입니다. BMI 수치에 따라서 underweight, healthy weight, overweight, 그리고 obese로 범주화 합니다.
BMI 값은 아래식으로 도출되고, 남성과 여성의 차이는 없습니다.
NIH (National Institute of Health)에서 제시한 BMI로 체지방 정도를 범주화하는 기준은 아래와 같습니다.
BMI Categories :
- Underweight = <18.5
- Normal weight = 18.5–24.9
- Overweight = 25–29.9
- Obesity = BMI of 30 or greater
TCGA 대장암 임상데이터에서 체중과 신장은 각각 kg과 cm 단위로 사용하므로 신장을 m 단위로 환산해야 합니다. 그러므로 BMI 계산은 \(체중 \times ({{신장}\div{100}})^{2}\)으로 해서, BMI라는 새로운 column을 생성토록 합니다.
df_clinic_tumor["BMI"] = df_clinic_tumor["weight"] / np.power(df_clinic_tumor["height"]/100, 2)
저번 포스팅의 scatter matrix에서 확인 했듯 신장 값 중 이상치 값인지 알 수 없는 값이 보였기 때문에 (BMI는 체중과 신장으로 유도되는 값이므로), BMI로 확인 가능합니다.
df_clinic_tumor[(df_clinic_tumor["BMI"] > 40) | (df_clinic_tumor["BMI"] < 15)]
위 그림에서 보이다싶이, TCGA-NH-A8F7-01 환자의 BMI가 271이고 신장과 체중이 뒤바뀐 것으로 보입니다. 이 샘플을 제거할 수도 있겠지만, 여기서는 정정토록 하겠습니다.
h, w = df_clinic_tumor.loc["TCGA-NH-A8F7-01"][["height", "weight"]]
df_clinic_tumor.set_value("TCGA-NH-A8F7-01", "height", w)
df_clinic_tumor.set_value("TCGA-NH-A8F7-01", "weight", h)
df_clinic_tumor.set_value("TCGA-NH-A8F7-01", "BMI", h / (w / 100)**2)
df_clinic_tumor.loc["TCGA-NH-A8F7-01"]
앞서 BMI로 체지방 정도를 범주화하는 기준에 대해서 언급했습니다. 환자들의 계산된 BMI로 범주화 합니다.
bins = [0, 18.5, 24.9, 29.9, 100]
bin_labels = ["Underweight", "Healthy weight", "Overweight", "Obesity"]
df_clinic_tumor["BMI category"] = pd.cut(df_clinic_tumor["BMI"], bins=bins, labels=bin_labels)
df_clinic_tumor
위 코드의 bins에 list로 할당한 값은 각 구간의 값이고, 기본값으로는 미만값을 기입하고, 제일 마지막은 극단값을 임의로 설정하면 됩니다. 예를 들어, 연령을 0~9, 10~19, 20~29 등으로 나누고자 한다면, bins = [0, 10, 20, 30, 40, 50, 60, 150] 이런 형태로 설정하면 됩니다. bin_labels는 해당 구간에 할당될 label값이며 항상 number of bins - 1만큼의 길이가 됩니다.
생존기간 시각화
의과학 분야에서 폭넓게 사용하는 생존분석은 다음 포스팅에서 다루려합니다. 여기서는 생존기간에 대한 일반적인 시각화 예제만 다루려 합니다.
우선 생존기간 변수를 적정한 범위로 계급 (bin)을 나누겠습니다. 여기서는 6개월, 1년, 3년, 그리고 5년 초과로 설정하겠습니다.
bins = [0, 180, 365, 1095, 10000]
bin_labels = ["6M", "1Y", "3Y", "5Y+"]
df_clinic_tumor["OS Bin"] = pd.cut(df_clinic_tumor["_OS"], bins=bins, labels=bin_labels)
Seaborn 모듈의 factorplot으로 각 체지방 범주별로 성별간 생존기간 차이를 보도록 하겠습니다.
sns.set(style="whitegrid")
# Draw a pointplot to show pulse as a function of two categorical factors
g = sns.factorplot(x="OS Bin", y="_OS", hue="gender", col="BMI category", data=df_clinic_tumor,
capsize=.2, size=6, aspect=.75)
g.despine(left=True)
Healthy weight와 Obese의 경우 여성이 남성보다 생존기간 중앙값이 좀 더 큽니다. 그런데 Overweight인 남성이 Healthy weight인 남성보다 5년 초과 (완치판정 받은 환자) 생존기간의 중앙값이 더 큽니다. 과체중 내지 비만은 암에 악영향을 끼치는 것으로 매스컴은 종종 기사화하는데, 이 데이터가 이상한 것일까요?
이번엔 사망한 환자만을 대상으로 살펴보겠습니다.
g = sns.factorplot(x="OS Bin", y="_OS", hue="BMI category", col="gender",
data=df_clinic_tumor[df_clinic_tumor["_OS_IND"] == 1],
capsize=.2, size=6, aspect=.75)
g.despine(left=True)
사망한 환자 중 남성의 경우 Healthy weight인 환자의 생존기간이 좀 더 길어보입니다. 이 TCGA 대장암 데이터가 생성될 당시 생존해있던 환자들 대상으로 살펴보면 어떨까요?
g = sns.factorplot(x="OS Bin", y="_OS", hue="BMI category", col="gender",
data=df_clinic_tumor[df_clinic_tumor["_OS_IND"] == 0],
capsize=.2, size=6, aspect=.75)
g.despine(left=True)
남성의 경우 5년 초과 생존 그룹에서는 오히려 Overweight인 환자의 생존 기간이 더 긴 경향을 보이고 있습니다. 여성의 경우 저정도의 차이가 통계적으로 유의하게 차이가 나는지 눈으로는 명징하지 않아 보입니다.
다음 포스팅에서는 생존 분석 (survival analysis)를 통해 체지방 정도가 생존에 영향을 끼치는지 살펴보도록 하겠습니다.







2018년에는 두루 평안하시길!
Thanks for your good posts, I followed you!