[英]Using lambda if condition to column based on value of another column in Pandas dataframe
[英]How to replace column value with another rows column value based on condition using pandas?
有没有更好的方法来进行以下操作?
df = pd.DataFrame(data={
"id": ['a', 'a', 'a', 'b', 'b', 'b', 'b'],
"date": ["2020-01-01", "2020-01-11", "2020-01-10", "2020-01-06", "2020-02-01", "2020-02-22", "2020-02-20"],
"type": ["start", "start", "closing", "start", "start", "closing", "closing"],
})
for id in df['id'].unique():
closing_date = df.loc[(df['id'] == id) & (df['type'] == 'closing'), 'date'].min()
df.loc[(df['id'] == id) & (df['date'] > closing_date), 'date'] = closing_date
我认为您可以在您开始使用的完全程序化(但相当可读)方法和其他答案中更完整的 pandas (但可读性较差,恕我直言)方法之间找到一个很好的中间立场,方法是将您的逻辑弹出为一个 function 在一个只有“id”的子数据帧上运行,然后简单地应用:
def make_start_precede_close(subdf):
closing_date = subdf.loc[subdf['type'] == 'closing', 'date'].min()
subdf.loc[subdf['date'] > closing_date, 'date'] = closing_date
return subdf
df.groupby("id").apply(make_start_precede_close)
最终,您必须在可测试性、可重用性、可读性和性能之间做出权衡。 Pure-pandas 可能会在性能上获胜(尽管不一定),但根据我的经验,在其他类别中弹出明确的 function 会获胜。
避免逐行(或逐个标识)做事。 首先,我对变量id
进行分组并找到最小日期。 然后我将这些数据与原始 dataframe 合并以创建一个closing_date
列,该列对每一行都有一个值。 现在我们只需要从原始列date
和closing_date
中取最小值。 最后,我们删除了closing_date
列。
closing_date = df[df['type'] == 'closing'].groupby('id').date.min()
df['closing_date'] = df.merge(closing_date, on='id').date_y
df['date'] = df[['date', 'closing_date']].min(axis=1)
df = df.drop(columns='closing_date')
Output:
id date type
0 a 2020-01-01 start
1 a 2020-01-10 start
2 a 2020-01-10 closing
3 b 2020-01-06 start
4 b 2020-02-01 start
5 b 2020-02-20 start
6 b 2020-02-20 closing
您可以使用groupby.transform
获取每个组的结束日期,然后用 boolean 索引替换较大的值:
closing = (df['date'].where(df['type'].eq('closing'))
.groupby(df['id']).transform('last')
)
df.loc[df['date'].gt(closing), 'date'] = closing
output:
id date type
0 a 2020-01-01 start
1 a 2020-01-10 start
2 a 2020-01-10 closing
3 b 2020-01-06 start
4 b 2020-02-01 start
5 b 2020-02-20 start
6 b 2020-02-20 closing
如果您每个 id 有多个“关闭”并希望确保获得最新的:
closing = (df['date'].sort_values()
.where(df['type'].eq('closing'))
.groupby(df['id']).transform('last')
)
df.loc[df['date'].gt(closing), 'date'] = closing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.