使用列名在 Python Pandas 中将宽日期转换为长数据
Wide date to long data conversion in Python Pandas using column names
我在 Python Pandas 中有一个宽数据框,如下所示:
import pandas as pd
import numpy as np
df = pd.DataFrame({'student_id' :[100, 101, 102],
'q1.cta1_count':[0, 1, 1],
'q1.cta1_date' :[np.nan, '2019-03-26', '2019-03-25' ],
'q1.cta1.reminder_count' :[0, 1, 0],
'q1.cta1.reminder_date' :[np.nan, '2019-03-31', np.nan]})
df
我需要转换为长格式,使其看起来像这样的数据框:
# student_id type count date
# 100 q1.cta1 0 NaN
# 100 q1.cta1.reminder 0 NaN
# 101 q1.cta1 1 2019-03-26
# 101 q1.cta1.reminder 1 2019-03-31
# 102 q1.cta1 1 2019-03-25
# 102 q1.cta1.reminder 0 NaN
我该怎么做?
您可以使用 pandas wide to long, but first you need to reshape the columns to fit pandas wide to long 格式:
df.columns = ["_".join(entry.split("_")[::-1])
if entry.endswith(("count", "date"))
else entry
for entry in df.columns]
现在,您可以重塑数据:
pd.wide_to_long(df,
["count", "date"],
i="student_id",
j="type",
sep="_",
suffix=".+").reset_index()
student_id type count date
0 100 q1.cta1 0 NaN
1 101 q1.cta1 1 2019-03-26
2 102 q1.cta1 1 2019-03-25
3 100 q1.cta1.reminder 0 NaN
4 101 q1.cta1.reminder 1 2019-03-31
5 102 q1.cta1.reminder 0 NaN
或者,您可以使用 pyjanitor 的 pivot_longer function, which is built on pandas' melt 函数,并提供更多的灵活性(完全公开,我是图书馆的贡献者):
import pyjanitor
df.pivot_longer(index="student_id",
names_to=("type", ".value"),
names_sep="_")
student_id type count date
0 100 q1.cta1 0 NaN
1 100 q1.cta1.reminder 0 NaN
2 101 q1.cta1 1 2019-03-26
3 101 q1.cta1.reminder 1 2019-03-31
4 102 q1.cta1 1 2019-03-25
5 102 q1.cta1.reminder 0 NaN
df = df.set_index('student_id')
df = pd.concat([
df[['q1.cta1_count', 'q1.cta1_date']].assign(type='q1.cta1').rename(columns={'q1.cta1_date':'date', 'q1.cta1_count':'count'}),
df[['q1.cta1.reminder_count', 'q1.cta1.reminder_date']].assign(type='q1.cta1_reminder').rename(columns={'q1.cta1.reminder_date':'date', 'q1.cta1.reminder_count':'count'})
]).sort_index().reset_index()
print(df)
打印:
student_id count date type
0 100 0 NaN q1.cta1
1 100 0 NaN q1.cta1_reminder
2 101 1 2019-03-26 q1.cta1
3 101 1 2019-03-31 q1.cta1_reminder
4 102 1 2019-03-25 q1.cta1
5 102 0 NaN q1.cta1_reminder
解法:
从v0.20开始,melt
是一阶函数,可以用
import pandas as pd
import numpy as np
df = pd.DataFrame({'student_id' :[100, 101, 102],
'q1.cta1_count':[0, 1, 1],
'q1.cta1_date' :[np.nan, '2019-03-26', '2019-03-25' ],
'q1.cta1.reminder_count' :[0, 1, 0],
'q1.cta1.reminder_date' :[np.nan, '2019-03-31', np.nan]})
df
df.rename(columns={'q1.cta1_count': 'q1.cta1', 'q1.cta1.reminder_count': 'q1.cta1.reminder'}, inplace=True)
df[['student_id', 'q1.cta1', 'q1.cta1_date']]\
.melt(id_vars=['student_id', 'q1.cta1_date'], var_name='q1.cta1', value_name='count')\
.rename(columns={'q1.cta1_date': 'date', 'q1.cta1': 'type'})\
.append(
df[['student_id', 'q1.cta1.reminder', 'q1.cta1.reminder_date']]\
.melt(id_vars=['student_id', 'q1.cta1.reminder_date'], var_name='q1.cta1.reminder', value_name='count')\
.rename(columns={'q1.cta1.reminder_date': 'date', 'q1.cta1.reminder': 'type'})\
, ignore_index=True)\
.sort_values(['student_id'])[['student_id', 'type', 'count', 'date']]
打印:
student_id type count date
0 100 q1.cta1 0 NaN
3 100 q1.cta1.reminder 0 NaN
1 101 q1.cta1 1 2019-03-26
4 101 q1.cta1.reminder 1 2019-03-31
2 102 q1.cta1 1 2019-03-25
5 102 q1.cta1.reminder 0 NaN
我在 Python Pandas 中有一个宽数据框,如下所示:
import pandas as pd
import numpy as np
df = pd.DataFrame({'student_id' :[100, 101, 102],
'q1.cta1_count':[0, 1, 1],
'q1.cta1_date' :[np.nan, '2019-03-26', '2019-03-25' ],
'q1.cta1.reminder_count' :[0, 1, 0],
'q1.cta1.reminder_date' :[np.nan, '2019-03-31', np.nan]})
df
我需要转换为长格式,使其看起来像这样的数据框:
# student_id type count date
# 100 q1.cta1 0 NaN
# 100 q1.cta1.reminder 0 NaN
# 101 q1.cta1 1 2019-03-26
# 101 q1.cta1.reminder 1 2019-03-31
# 102 q1.cta1 1 2019-03-25
# 102 q1.cta1.reminder 0 NaN
我该怎么做?
您可以使用 pandas wide to long, but first you need to reshape the columns to fit pandas wide to long 格式:
df.columns = ["_".join(entry.split("_")[::-1])
if entry.endswith(("count", "date"))
else entry
for entry in df.columns]
现在,您可以重塑数据:
pd.wide_to_long(df,
["count", "date"],
i="student_id",
j="type",
sep="_",
suffix=".+").reset_index()
student_id type count date
0 100 q1.cta1 0 NaN
1 101 q1.cta1 1 2019-03-26
2 102 q1.cta1 1 2019-03-25
3 100 q1.cta1.reminder 0 NaN
4 101 q1.cta1.reminder 1 2019-03-31
5 102 q1.cta1.reminder 0 NaN
或者,您可以使用 pyjanitor 的 pivot_longer function, which is built on pandas' melt 函数,并提供更多的灵活性(完全公开,我是图书馆的贡献者):
import pyjanitor
df.pivot_longer(index="student_id",
names_to=("type", ".value"),
names_sep="_")
student_id type count date
0 100 q1.cta1 0 NaN
1 100 q1.cta1.reminder 0 NaN
2 101 q1.cta1 1 2019-03-26
3 101 q1.cta1.reminder 1 2019-03-31
4 102 q1.cta1 1 2019-03-25
5 102 q1.cta1.reminder 0 NaN
df = df.set_index('student_id')
df = pd.concat([
df[['q1.cta1_count', 'q1.cta1_date']].assign(type='q1.cta1').rename(columns={'q1.cta1_date':'date', 'q1.cta1_count':'count'}),
df[['q1.cta1.reminder_count', 'q1.cta1.reminder_date']].assign(type='q1.cta1_reminder').rename(columns={'q1.cta1.reminder_date':'date', 'q1.cta1.reminder_count':'count'})
]).sort_index().reset_index()
print(df)
打印:
student_id count date type
0 100 0 NaN q1.cta1
1 100 0 NaN q1.cta1_reminder
2 101 1 2019-03-26 q1.cta1
3 101 1 2019-03-31 q1.cta1_reminder
4 102 1 2019-03-25 q1.cta1
5 102 0 NaN q1.cta1_reminder
解法:
从v0.20开始,melt
是一阶函数,可以用
import pandas as pd
import numpy as np
df = pd.DataFrame({'student_id' :[100, 101, 102],
'q1.cta1_count':[0, 1, 1],
'q1.cta1_date' :[np.nan, '2019-03-26', '2019-03-25' ],
'q1.cta1.reminder_count' :[0, 1, 0],
'q1.cta1.reminder_date' :[np.nan, '2019-03-31', np.nan]})
df
df.rename(columns={'q1.cta1_count': 'q1.cta1', 'q1.cta1.reminder_count': 'q1.cta1.reminder'}, inplace=True)
df[['student_id', 'q1.cta1', 'q1.cta1_date']]\
.melt(id_vars=['student_id', 'q1.cta1_date'], var_name='q1.cta1', value_name='count')\
.rename(columns={'q1.cta1_date': 'date', 'q1.cta1': 'type'})\
.append(
df[['student_id', 'q1.cta1.reminder', 'q1.cta1.reminder_date']]\
.melt(id_vars=['student_id', 'q1.cta1.reminder_date'], var_name='q1.cta1.reminder', value_name='count')\
.rename(columns={'q1.cta1.reminder_date': 'date', 'q1.cta1.reminder': 'type'})\
, ignore_index=True)\
.sort_values(['student_id'])[['student_id', 'type', 'count', 'date']]
打印:
student_id type count date
0 100 q1.cta1 0 NaN
3 100 q1.cta1.reminder 0 NaN
1 101 q1.cta1 1 2019-03-26
4 101 q1.cta1.reminder 1 2019-03-31
2 102 q1.cta1 1 2019-03-25
5 102 q1.cta1.reminder 0 NaN