如何将数据从宽数据转换为长数据,以便根据时间绘制值
How to convert data from wide to long so values are plotted against time
我有一个包含多个ID和多个变量的时间序列数据集,每个变量有3个时间序列条目——“基线”、“3个月”、“6个月”。数据框的结构如下,df =
import pandas as pd
data = {'Patient ID': [11111, 11111, 11111, 11111, 22222, 22222, 22222, 22222, 33333, 33333, 33333, 33333, 44444, 44444, 44444, 44444, 55555, 55555, 55555, 55555],
'Lab Attribute': ['% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)'],
'Baseline': [46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0],
'3 Month': [23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0],
'6 Month': [34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0]}
df = pd.DataFrame(data)
Patient ID Lab Attribute Baseline 3 Month 6 Month
0 11111 % Saturation- Iron 46.0 23.0 34.0
1 11111 ALK PHOS 94.0 82.0 65.0
2 11111 ALT(SGPT) 21.0 13.0 10.0
3 11111 AST (SGOT) 18.0 17.0 14.0
4 22222 % Saturation- Iron 46.0 23.0 34.0
5 22222 ALK PHOS 94.0 82.0 65.0
6 22222 ALT(SGPT) 21.0 13.0 10.0
7 22222 AST (SGOT) 18.0 17.0 14.0
8 33333 % Saturation- Iron 46.0 23.0 34.0
9 33333 ALK PHOS 94.0 82.0 65.0
10 33333 ALT(SGPT) 21.0 13.0 10.0
11 33333 AST (SGOT) 18.0 17.0 14.0
12 44444 % Saturation- Iron 46.0 23.0 34.0
13 44444 ALK PHOS 94.0 82.0 65.0
14 44444 ALT(SGPT) 21.0 13.0 10.0
15 44444 AST (SGOT) 18.0 17.0 14.0
16 55555 % Saturation- Iron 46.0 23.0 34.0
17 55555 ALK PHOS 94.0 82.0 65.0
18 55555 ALT(SGPT) 21.0 13.0 10.0
19 55555 AST (SGOT) 18.0 17.0 14.0
我想做的是按 ID 和实验室属性分组,并创建每个“实验室属性”的图 - % 饱和度 - 铁、ALK PHOS 等,其中将包括所有的时间序列患者 ID。
因此,根据示例数据,将有 4 个图 - % Saturation- Iron、ALK PHOS 等,每个图包含 5 个迹线(每个 ID 1 个)。
我尝试根据这篇文章使用 groupby -
尽管它只是将所有内容绘制在一张图表上。
这是我目前的代码:
df_labs = pd.read_csv("/Users/johnconor/Documents/Python/gut_microbiome/out/nw_labs_up_to_6mon.csv")
df_labs = df_labs.fillna(method='ffill')
dfl = df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().plot()
这是结果:
[![在此处输入图片描述][1]][1]
我遇到的部分问题是我能找到的所有示例都包含只有 1 个值列的长格式数据。不是随时间变化的数值。
我还尝试根据这篇文章将该方法用于多个地块 -
n_ids = df_labs.Patient_ID.unique().size
n_cols = int(n_ids ** 0.5)
n_rows = n_cols + (1 if n_ids % n_cols else 0)
fig, axes = plt.subplots(n_rows, n_cols)
axes = axes.ravel()
for i, (id, att, base,three,six) in enumerate(df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().reset_index()):
print(idx)
series.plot(ax=axes[i], title=f"ID:{idx}")
fig.tight_layout()
尽管我 运行 遇到了问题,因为它再次仅针对一组值设计。产生错误:
ValueError: too many values to unpack (expected 5)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-40-42cf5bc14bdb> in <module>
4 fig, axes = plt.subplots(n_rows, n_cols)
5 axes = axes.ravel()
----> 6 for i, (id, att, base,three,six) in enumerate(df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().reset_index()):
7 print(idx)
8 series.plot(ax=axes[i], title=f"ID:{idx}")
ValueError: too many values to unpack (expected 5)
- 应使用
.melt
将数据框的形状更改为长格式,这将允许将月份用作时间轴。
- 使用
seaborn.relplot
和 kind='line'
来创建可视化是最简单的。
- 更改
col
、row
、and/or hue
以调整数据的分组方式。不要更改 x
和 y
.
- 要防止共享
y
,请参阅
import pandas as pd
import seaborn as sns
# reshape the dataframe
dfm = df.melt(id_vars=['Patient ID', 'Lab Attribute'], var_name='Months')
# change the Months values to numeric
dfm.Months = dfm.Months.map({'Baseline': 0, '3 Month': 3, '6 Month': 6})
# display(dfm.head())
Patient ID Lab Attribute Months value
0 11111 % Saturation- Iron 0 46.0
1 11111 ALK PHOS 0 94.0
2 11111 ALT(SGPT) 0 21.0
3 11111 AST (SGOT) 0 18.0
4 22222 % Saturation- Iron 0 46.0
# plot a figure level line plot with seaborn
p = sns.relplot(data=dfm, col='Lab Attribute', x='Months', y='value', hue='Patient ID', kind='line', col_wrap=4, marker='o', palette='husl')
- 由于数据值完全相同,因此行被堆叠
- 使用
seaborn.catplot
和 kind='bar'
进行条形图可视化
p = sns.catplot(data=dfm, col='Lab Attribute', x='Months', y='value', hue='Patient ID', kind='bar', col_wrap=4)
我有一个包含多个ID和多个变量的时间序列数据集,每个变量有3个时间序列条目——“基线”、“3个月”、“6个月”。数据框的结构如下,df =
import pandas as pd
data = {'Patient ID': [11111, 11111, 11111, 11111, 22222, 22222, 22222, 22222, 33333, 33333, 33333, 33333, 44444, 44444, 44444, 44444, 55555, 55555, 55555, 55555],
'Lab Attribute': ['% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)', '% Saturation- Iron', 'ALK PHOS', 'ALT(SGPT)', 'AST (SGOT)'],
'Baseline': [46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0, 46.0, 94.0, 21.0, 18.0],
'3 Month': [23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0, 23.0, 82.0, 13.0, 17.0],
'6 Month': [34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0, 34.0, 65.0, 10.0, 14.0]}
df = pd.DataFrame(data)
Patient ID Lab Attribute Baseline 3 Month 6 Month
0 11111 % Saturation- Iron 46.0 23.0 34.0
1 11111 ALK PHOS 94.0 82.0 65.0
2 11111 ALT(SGPT) 21.0 13.0 10.0
3 11111 AST (SGOT) 18.0 17.0 14.0
4 22222 % Saturation- Iron 46.0 23.0 34.0
5 22222 ALK PHOS 94.0 82.0 65.0
6 22222 ALT(SGPT) 21.0 13.0 10.0
7 22222 AST (SGOT) 18.0 17.0 14.0
8 33333 % Saturation- Iron 46.0 23.0 34.0
9 33333 ALK PHOS 94.0 82.0 65.0
10 33333 ALT(SGPT) 21.0 13.0 10.0
11 33333 AST (SGOT) 18.0 17.0 14.0
12 44444 % Saturation- Iron 46.0 23.0 34.0
13 44444 ALK PHOS 94.0 82.0 65.0
14 44444 ALT(SGPT) 21.0 13.0 10.0
15 44444 AST (SGOT) 18.0 17.0 14.0
16 55555 % Saturation- Iron 46.0 23.0 34.0
17 55555 ALK PHOS 94.0 82.0 65.0
18 55555 ALT(SGPT) 21.0 13.0 10.0
19 55555 AST (SGOT) 18.0 17.0 14.0
我想做的是按 ID 和实验室属性分组,并创建每个“实验室属性”的图 - % 饱和度 - 铁、ALK PHOS 等,其中将包括所有的时间序列患者 ID。
因此,根据示例数据,将有 4 个图 - % Saturation- Iron、ALK PHOS 等,每个图包含 5 个迹线(每个 ID 1 个)。
我尝试根据这篇文章使用 groupby -
尽管它只是将所有内容绘制在一张图表上。
这是我目前的代码:
df_labs = pd.read_csv("/Users/johnconor/Documents/Python/gut_microbiome/out/nw_labs_up_to_6mon.csv")
df_labs = df_labs.fillna(method='ffill')
dfl = df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().plot()
这是结果:
[![在此处输入图片描述][1]][1]
我遇到的部分问题是我能找到的所有示例都包含只有 1 个值列的长格式数据。不是随时间变化的数值。
我还尝试根据这篇文章将该方法用于多个地块 -
n_ids = df_labs.Patient_ID.unique().size
n_cols = int(n_ids ** 0.5)
n_rows = n_cols + (1 if n_ids % n_cols else 0)
fig, axes = plt.subplots(n_rows, n_cols)
axes = axes.ravel()
for i, (id, att, base,three,six) in enumerate(df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().reset_index()):
print(idx)
series.plot(ax=axes[i], title=f"ID:{idx}")
fig.tight_layout()
尽管我 运行 遇到了问题,因为它再次仅针对一组值设计。产生错误:
ValueError: too many values to unpack (expected 5)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-40-42cf5bc14bdb> in <module>
4 fig, axes = plt.subplots(n_rows, n_cols)
5 axes = axes.ravel()
----> 6 for i, (id, att, base,three,six) in enumerate(df_labs.groupby(['Patient_ID', 'Lab_Attribute'])['Baseline','3 Month','6 Month'].sum().reset_index()):
7 print(idx)
8 series.plot(ax=axes[i], title=f"ID:{idx}")
ValueError: too many values to unpack (expected 5)
- 应使用
.melt
将数据框的形状更改为长格式,这将允许将月份用作时间轴。 - 使用
seaborn.relplot
和kind='line'
来创建可视化是最简单的。- 更改
col
、row
、and/orhue
以调整数据的分组方式。不要更改x
和y
.
- 更改
- 要防止共享
y
,请参阅
import pandas as pd
import seaborn as sns
# reshape the dataframe
dfm = df.melt(id_vars=['Patient ID', 'Lab Attribute'], var_name='Months')
# change the Months values to numeric
dfm.Months = dfm.Months.map({'Baseline': 0, '3 Month': 3, '6 Month': 6})
# display(dfm.head())
Patient ID Lab Attribute Months value
0 11111 % Saturation- Iron 0 46.0
1 11111 ALK PHOS 0 94.0
2 11111 ALT(SGPT) 0 21.0
3 11111 AST (SGOT) 0 18.0
4 22222 % Saturation- Iron 0 46.0
# plot a figure level line plot with seaborn
p = sns.relplot(data=dfm, col='Lab Attribute', x='Months', y='value', hue='Patient ID', kind='line', col_wrap=4, marker='o', palette='husl')
- 由于数据值完全相同,因此行被堆叠
- 使用
seaborn.catplot
和kind='bar'
进行条形图可视化
p = sns.catplot(data=dfm, col='Lab Attribute', x='Months', y='value', hue='Patient ID', kind='bar', col_wrap=4)