我有一个以下形式的 pandas 数据框:
df
ID col_1 col_2 col_3 Date
1 20 40 1/1/2018
1 10 1/2/2018
1 50 60 1/3/2018
3 40 10 90 1/1/2018
4 80 80 1/1/2018
问题是,我需要创建一个新的数据帧,其中每列的第一个有效值,但还有从“日期”派生的附加列,这些列对应于这些值在原始数据帧中匹配的时间。
换句话说:
new_df
ID first_col_1 Date_col_1 first_col_2 Date_col_2 first_col_3 Date_col_3
1 10 1/2/2018 20 1/1/2018 40 1/1/2018
3 40 1/1/2018 10 1/1/2018 90 1/1/2018
4 1/1/2018 80 1/1/2018 80 1/1/2018
据我了解,获取每个 ID 每列的第一个有效值就像这样简单
df.groupby('ID').first()
但是如何提取每列的相关“日期”信息?
最佳答案
您不需要循环,但您确实需要在分组操作之前“融化”数据框。
所以从以下开始:
from io import StringIO
import pandas
f = StringIO("""\
ID,col_1,col_2,col_3,Date
1,,20,40,1/1/2018
1,10,,,1/2/2018
1,50,,60,1/3/2018
3,40,10,90,1/1/2018
4,,80,80,1/1/2018
""")
df = pandas.read_csv(f)
然后您可以:
print(
df.melt(id_vars=['ID', 'Date'], value_vars=['col_1', 'col_2', 'col_3'], value_name='first')
.groupby(by=['ID', 'variable'])
.first()
.unstack(level='variable')
)
这给你:
Date first
variable col_1 col_2 col_3 col_1 col_2 col_3
ID
1 1/1/2018 1/1/2018 1/1/2018 10.0 20.0 40.0
3 1/1/2018 1/1/2018 1/1/2018 40.0 10.0 90.0
4 1/1/2018 1/1/2018 1/1/2018 NaN 80.0 80.0
这些列是多级的,因此如果您愿意,我们可以对它们进行一些修饰:
def flatten_columns(df, sep='_'):
newcols = [sep.join(_) for _ in df.columns]
return df.set_axis(newcols, axis='columns', inplace=False)
print(
df.melt(id_vars=['ID', 'Date'], value_vars=['col_1', 'col_2', 'col_3'], value_name='first')
.groupby(by=['ID', 'variable'])
.first()
.unstack(level='variable')
.sort_index(level='variable', axis='columns')
.pipe(flatten_columns)
)
这为您提供了与您的示例不完全相同的列顺序,但它与我想要的非常接近。
Date_col_1 first_col_1 Date_col_2 first_col_2 Date_col_3 first_col_3
ID
1 1/1/2018 10.0 1/1/2018 20.0 1/1/2018 40.0
3 1/1/2018 40.0 1/1/2018 10.0 1/1/2018 90.0
4 1/1/2018 NaN 1/1/2018 80.0 1/1/2018 80.0
关于python - 如何在 groupby 之后合并列并选择 pandas 数据框中其他列的第一个有效值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53661605/