Python实战:抑郁症诊疗数据的处理与可视化分析

        在当今数字化时代,数据无处不在,而如何从海量的数据中提取有价值的信息,成为了众多领域关注的焦点。在医疗领域,患者的诊疗数据蕴含着丰富的信息,通过对这些数据的深入分析,可以为医疗决策、疾病研究等提供有力支持。Python 作为一种功能强大且易于上手的编程语言,在数据处理和分析领域占据着重要地位。它拥有众多丰富的库,如 Pandas 用于数据处理,pyecharts 用于数据可视化等,这些库大大简化了数据处理和分析的流程。本文将通过一个实际的抑郁症诊疗数据案例,详细介绍如何使用 Python 进行数据的导入、预处理、分析以及可视化,希望能为读者在相关领域的学习和实践提供有益的参考。

        本次分析的数据来源于一个名为 “E:\YiYuZheng.csv” 的 CSV 文件,该文件包含了大量抑郁症患者的诊疗记录。在 Python 中,我们使用 Pandas 库来读取和处理 CSV 文件。Pandas 是一个开源的、BSD 许可的库,提供了高性能、易于使用的数据结构和数据分析工具。
首先,我们需要确保已经安装了 Pandas 库。如果尚未安装,可以使用 pip 命令进行安装:        安装完成后,在 Python 代码中导入 Pandas 库,并读取 CSV 文件:        在上述代码中,pd.read_csv()函数用于读取 CSV 文件,参数r'E:\YiYuZheng.csv'指定了文件的路径。这里使用了原始字符串前缀r,以确保路径中的反斜杠不会被误解为转义字符。
读取数据后,我们可以使用head()方法查看数据的前几行,以初步了解数据的结构和内容:

Patient_name Label Date Title Communications Doctor Hospital Faculty
患者:女 43 岁 压抑 05.28 压抑 个人情况:去年 1 月份开始夫妻两地分居,孩子 13 岁男孩住校,平… 这种情况是否需要去… 115 杨胜文 襄阳市安定医院 心理科
从输出结果可以看出,数据集中包含了患者姓名(Patient_name)、症状标签(Label)、就诊日期(Date)、病情描述标题(Title)、沟通次数(Communications)、医生姓名(Doctor)、医院名称(Hospital)以及科室(Faculty)等字段。
为了更全面地了解数据的信息,我们还可以使用info()方法查看数据的详细信息,包括每列的数据类型、非空值数量等:
df.info()

输出结果如下:

plaintext                                                                                                                                             

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8400 entries, 0 to 8399
Data columns (total 8 columns):
 #   Column          Non-Null Count  Dtype 
---  ------          --------------  ----- 
 0   Patient_name    8400 non-null   object
 1   Label           8400 non-null   object
 2   Date            8288 non-null   object
 3   Title           8400 non-null   object
 4   Communications  8400 non-null   int64 
 5   Doctor          8400 non-null   object
 6   Hospital        8400 non-null   object
 7   Faculty         8400 non-null   object
dtypes: int64(1), object(7)
memory usage: 525.1+ KB

通过info()方法的输出,我们发现Date列存在 112 个空缺值,并且数据类型为对象(即字符串类型),并非日期类型。同时,Patient_name列中的信息混合在一起,需要进一步拆分出年龄和性别,以便后续的分析。这些发现为我们后续的数据预处理工作指明了方向。

三、数据预处理

3.1 拆分年龄和性别

Patient_name列中,数据的格式为 “患者:女 43 岁”,我们需要将其中的性别和年龄信息提取出来,分别存储在新的列中。
首先,提取性别信息。我们可以使用字符串的split()方法,按照空格将字符串拆分成多个部分,然后再按照冒号进行二次拆分,从而获取性别信息。在 Python 中,可以使用map()函数结合lambda表达式来实现这一操作:

python

df['Sex'] = df['Patient_name'].map(lambda x: x.split(" ")[0]).map(lambda x: x.split(":")[-1])

在上述代码中,第一个map()函数将Patient_name列中的每个字符串按照空格拆分,并取第一个部分,例如 “患者:女 43 岁” 拆分成 “患者:女”。第二个map()函数再将得到的结果按照冒号拆分,并取最后一个部分,即性别 “女”。最终,将提取到的性别信息存储在新的列Sex中。
接下来,提取年龄信息。同样使用split()方法,按照空格拆分字符串后,取第三个部分,并去除末尾的 “岁” 字:

python

df['Age'] = df['Patient_name'].map(lambda x: x.split(" ")[2][:-1])

通过上述操作,我们成功地从Patient_name列中提取出了性别和年龄信息,并分别存储在SexAge列中。此时,我们可以再次使用head()方法查看数据,确认新列的添加和数据提取是否正确:

python

df.head()

输出结果如下:

Patient_name Label Date Title Communications Doctor Hospital Faculty Sex Age
患者:女 43 岁 压抑 05.28 压抑 个人情况:去年 1 月份开始夫妻两地分居,孩子 13 岁男孩住校,平… 这种情况是否需要去… 115 杨胜文 襄阳市安定医院 心理科 43
可以看到,SexAge列已经成功添加到数据集中,并且数据提取正确。

3.2 处理空缺值

在数据处理中,空缺值是一个常见的问题。对于存在空缺值的数据,我们需要根据具体情况选择合适的处理方法。在本次数据集中,Date列存在 112 个空缺值。由于空缺数据较少,并且不适合使用填充法(例如填充均值、中位数等方法可能会引入偏差),因此我们选择直接删除包含空缺值的行。
在 Pandas 中,可以使用dropna()方法来删除包含空缺值的行。如果希望在原数据上进行修改,可以设置inplace=True参数:

python

df.dropna(inplace=True)

执行上述代码后,再次使用info()方法查看数据信息:

python

df.info()

输出结果如下:

plaintext

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8288 entries, 0 to 8287
Data columns (total 10 columns):
 #   Column          Non-Null Count  Dtype 
---  ------          --------------  ----- 
 0   Patient_name    8288 non-null   object
 1   Label           8288 non-null   object
 2   Date            8288 non-null   object
 3   Title           8288 non-null   object
 4   Communications  8288 non-null   int64 
 5   Doctor          8288 non-null   object
 6   Hospital        8288 non-null   object
 7   Faculty         8288 non-null   object
 8   Sex             8288 non-null   object
 9   Age             8288 non-null   object
dtypes: int64(1), object(9)
memory usage: 656.4+ KB

从输出结果可以看出,数据集中的空缺值已经被成功删除,RangeIndex从原来的 8400 条减少到了 8288 条,并且所有列的非空值数量均为 8288,表明数据集中不再存在空缺值。

3.3 修改 Date 列格式

在原始数据中,Date列的数据类型为字符串,且格式不统一,部分数据只包含月和日,如 “05.28”,需要将其转换为统一的日期格式 “年 – 月 – 日”,并将数据类型转换为日期类型,以便后续进行日期相关的分析。
首先,将Date列的数据类型转换为字符串类型(虽然原本就是字符串类型,但为了确保一致性):

python

df['Date'] = df['Date'].astype(str)

然后,定义一个函数trans_date(),用于将日期字符串转换为统一格式:

python

def trans_date(tag):
    if tag.startswith("20"):
        tag = tag.replace(".", "-")
    else:
        tag = "2025-" + tag.replace(".", "-")
    return tag

在上述函数中,首先判断日期字符串是否以 “20” 开头,如果是,则说明已经包含年份,直接将字符串中的 “.” 替换为 “-”;如果不是,则在字符串前加上 “2025-”(假设数据的年份均为 2025 年,实际应用中可根据具体情况调整),并将 “.” 替换为 “-”。
接下来,使用map()函数调用trans_date()函数,对Date列中的每个日期字符串进行格式转换:

python

df['Date'] = df['Date'].map(lambda x: trans_date(x))

此时,Date列中的日期格式已经统一为 “年 – 月 – 日”,但数据类型仍然是字符串。最后,使用pd.to_datetime()函数将其转换为日期类型:

python

df['Date'] = pd.to_datetime(df['Date'])

经过上述处理,Date列的数据格式和类型均已符合要求。我们可以再次使用info()方法查看数据信息,确认Date列的数据类型已经变为datetime64[ns]

python

df.info()

输出结果如下:

plaintext

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8288 entries, 0 to 8287
Data columns (total 10 columns):
 #   Column          Non-Null Count  Dtype         
---  ------          --------------  -----         
 0   Patient_name    8288 non-null   object        
 1   Label           8288 non-null   object        
 2   Date            8288 non-null   datetime64[ns]
 3   Title           8288 non-null   object        
 4   Communications  8288 non-null   int64         
 5   Doctor          8288 non-null   object        
 6   Hospital        8288 non-null   object        
 7   Faculty         8288 non-null   object        
 8   Sex             8288 non-null   object        
 9   Age             8288 non-null   object        
dtypes: int64(1), object(9), datetime64[ns](1)
memory usage: 656.4+ KB

至此,数据预处理工作基本完成,经过清洗和转换后的数据为后续的数据分析和可视化奠定了良好的基础。

四、数据可视化分析

数据可视化是将数据以图形化的方式呈现,能够更直观地展示数据的特征和规律,帮助我们更好地理解数据背后的信息。在 Python 中,pyecharts 是一个功能强大的数据可视化库,它支持多种图表类型,如饼图、柱状图、折线图等,并且可以方便地在 Jupyter Notebook 等环境中进行展示。在进行可视化之前,我们先导入相关的库和模块:

python

from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.globals import ThemeType

4.1 患者性别分布情况

首先,我们来分析患者的性别分布情况。通过统计不同性别的患者数量,并使用饼图进行展示,可以直观地看出男女患者在数量上的比例关系。
我们使用value_counts()方法统计Sex列中不同性别的数量:

python

data = df['Sex'].value_counts()

value_counts()方法会返回一个包含每个唯一值出现次数的 Series 对象。接下来,将统计结果分别提取到xy变量中,用于后续的图表绘制:

python

x = data.index.tolist()
y = data.tolist()

在上述代码中,data.index.tolist()获取了 Series 对象的索引(即性别类别)并转换为列表,data.tolist()获取了 Series 对象的值(即每个性别的数量)并转换为列表。
然后,使用Pie类创建一个饼图,并进行相关设置:

python

pie = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))
   .add("", [list(z) for z in zip(x, y)], label_opts=opts.LabelOpts(formatter="{b}:{d}%"))
   .set_global_opts(title_opts=opts.TitleOpts(title="患者性别分布情况"))
)

在上述代码中:

  • Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))创建了一个Pie对象,并通过init_opts参数设置了图表的主题为深色主题(DARK),使图表看起来更加美观和专业。
  • .add("", [list(z) for z in zip(x, y)], label_opts=opts.LabelOpts(formatter="{b}:{d}%"))添加了数据到饼图中。[list(z) for z in zip(x, y)]xy列表中的元素一一对应地组合成元组,然后转换为列表,作为饼图的数据。label_opts=opts.LabelOpts(formatter="{b}:{d}%")设置了标签的格式,{b}表示标签名称(即性别),{d}%表示百分比,这样在饼图上会以 “性别:百分比” 的形式显示标签。
  • .set_global_opts(title_opts=opts.TitleOpts(title="患者性别分布情况"))设置了图表的全局选项,其中title_opts用于设置标题,标题内容为 “患者性别分布情况”。
    最后,使用render_notebook()方法在 Jupyter Notebook 中渲染图表:
  • python

    pie.render_notebook()
    

     

    通过上述步骤,我们成功绘制出了患者性别分布的饼图,从图中可以清晰地看出男女患者的比例情况,为进一步分析性别与抑郁症之间的关系提供了直观的数据支持。

    4.2 患者年龄分布情况

    接下来分析患者的年龄分布情况。由于原始的Age列数据存在一些不规范的情况,如部分数据包含 “天”“个”“月” 等字样,我们需要先对其进行处理,将年龄统一转换为数值类型。
    首先,使用map()函数和lambda表达式对不规范的年龄数据进行处理:

    python

    df['Age'] = df['Age'].map(lambda x: "1" if ("天" in x or "个" in x or "月" in x) else x).astype(int)
    

    在上述代码中,如果年龄字符串中包含 “天”“个” 或 “月” 字样,说明该年龄不是以岁为单位,我们将其统一转换为 “1”(表示 1 岁),否则保持原年龄值不变。然后,使用astype(int)方法将Age列的数据类型转换为整数类型。
    接下来,对年龄进行分箱处理,将年龄划分为不同的区间,并统计每个区间内的患者数量。我们定义了年龄区间的标签和对应的分箱边界:

    python

    labels = ["0~18", "19~40", "41~60", "61~80", "80+"]
    df['age_label'] = pd.cut(df['Age'], bins=[0, 18, 40, 60, 80, 100], labels=labels)
    

    在上述代码中,pd.cut()函数用于将Age列的数据按照指定的分箱边界[0, 18, 40, 60, 80, 100]进行分组,并为每个分组分配一个标签,标签存储在新的列age_label中。
    然后,统计每个年龄区间的患者数量:

    python

    data = df['age_label'].value_counts().sort_index()
    

    value_counts()方法统计每个年龄区间出现的次数,sort_index()方法按照索引(即年龄区间标签)进行排序,确保结果的顺序一致性。
    将统计结果提取到xy变量中:

    python

    x = data.index.tolist()
    y = data.tolist()
    

            通过本次对抑郁症诊疗数据的处理与分析,我们深刻体会到Python在数据领域的强大功能。从最初的数据导入,到繁杂的数据预处理,再到生动的数据可视化呈现,每一个步骤都紧密相连,缺一不可。数据预处理作为整个流程的基石,其重要性不言而喻。通过对数据的清洗、转换和整合,我们为后续的分析和可视化奠定了坚实基础,确保了分析结果的准确性和可靠性。而数据可视化则像是一把钥匙,打开了数据洞察的大门,将复杂的数据以直观、易懂的图表形式展现出来,让我们能够迅速捕捉到数据中的关键信息和潜在规律。 从性别分布来看,饼图清晰地呈现出男女患者的比例差异,这或许能为进一步研究性别与抑郁症的关联提供线索。在年龄分布方面,柱状图展示出不同年龄段患者的数量分布情况,为我们了解抑郁症在不同年龄段的发病特点提供了直观依据。就诊次数分布的折线图,则让我们对患者的就诊行为模式有了更深入的认识。这些可视化结果不仅有助于医疗从业者更深入地理解抑郁症患者群体的特征,也能为相关政策的制定和医疗资源的合理分配提供数据支持。 当然,本次分析也存在一些不足之处。在年龄处理环节,尽管我们对不规范数据进行了一定处理,但可能仍存在一些特殊情况未考虑周全。日期补全方面,假设所有缺失年份均为2025年可能与实际情况存在偏差。在未来的研究中,可以进一步探索更精准的年龄处理方法,以及通过更多渠道获取准确的年份信息,以提高数据的质量和分析结果的准确性。 展望未来,随着医疗数据的不断积累和技术的持续进步,我们有理由相信数据驱动的医疗分析将发挥更大的作用。一方面,我们可以将更多维度的数据纳入分析范围,如患者的生活习惯、遗传信息等,以更全面地揭示抑郁症的发病机制和影响因素。另一方面,结合机器学习等人工智能技术,构建预测模型,提前预测抑郁症的发病风险,实现疾病的早发现、早治疗。同时,希望本文的分析过程和方法能够为其他医疗数据的研究提供参考和借鉴,鼓励更多的人投身于医疗数据分析领域,为改善人类健康贡献自己的力量。 最后,感谢各位读者的耐心阅读。如果您在阅读过程中有任何疑问、建议或想法,欢迎在评论区留言分享。让我们一起在数据的海洋中探索,共同挖掘更多有价值的信息,为医疗事业的发展添砖加瓦。期待与您在数据的世界中再次相遇!  

     

    作者:黄锦炎

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python实战:抑郁症诊疗数据的处理与可视化分析

    发表回复