DataFrame列计算异常:基于Status生成Days列结果不符合预期
问题
我需要遍历DataFrame的['Status']列,根据其值计算['Days']列:
- 当状态为
Active时,计算['Date']列日期与今日的天数差 - 当状态为
Sold时,值设为0
但运行代码后,Sold行的Days未按预期设为0,而是都计算了日期差,和预期结果不符。
错误代码
import pandas as pd from datetime import date data={'Status':['Sold', 'Active', 'Sold', 'Active'], 'Date': ['2024-10-02', '2024-05-06', '2024-11-01', '2024-07-12' ], } df=pd.DataFrame(data) d=date.today() d=pd.to_datetime(d) df['Date']=pd.to_datetime(df['Date']) for i in df['Status']: if i=='Active': values=df['Date']-d else: values=0 df['Days']=values print(df)
预期输出
Status Date Days 0 Sold 2024-10-02 0 days 1 Active 2024-05-06 -204 days 2 Sold 2024-11-01 0 days 3 Active 2024-07-12 -137 days
实际输出
Status Date Days 0 Sold 2024-10-02 -55 days 1 Active 2024-05-06 -204 days 2 Sold 2024-11-01 -25 days 3 Active 2024-07-12 -137 days
问题原因
循环逻辑存在根本性错误:
- 遍历
df['Status']时,每次循环都会完全覆盖values变量。如果最后一条记录的Status是Active,values会被设置为全量的日期差;如果最后一条是Sold,values会被设为0。最终赋值给df['Days']时,只会保留最后一次循环的结果。 - 这种逐元素循环的方式不符合Pandas的向量化操作设计,不仅效率低下,还容易出现逻辑漏洞。
解决方法
方法1:使用numpy.where(推荐,向量化操作)
利用numpy.where实现条件判断,一次性生成结果,符合Pandas的最佳实践:
import pandas as pd from datetime import date import numpy as np data={'Status':['Sold', 'Active', 'Sold', 'Active'], 'Date': ['2024-10-02', '2024-05-06', '2024-11-01', '2024-07-12' ], } df=pd.DataFrame(data) today = pd.to_datetime(date.today()) df['Date']=pd.to_datetime(df['Date']) # 条件判断:Status为Active时计算日期差,否则设为0天 df['Days'] = np.where(df['Status'] == 'Active', df['Date'] - today, pd.Timedelta(days=0)) print(df)
方法2:使用df.apply(逐行处理,适合复杂逻辑)
如果需要处理更复杂的行级逻辑,可以使用apply逐行计算:
import pandas as pd from datetime import date data={'Status':['Sold', 'Active', 'Sold', 'Active'], 'Date': ['2024-10-02', '2024-05-06', '2024-11-01', '2024-07-12' ], } df=pd.DataFrame(data) today = pd.to_datetime(date.today()) df['Date']=pd.to_datetime(df['Date']) def calculate_days(row): if row['Status'] == 'Active': return row['Date'] - today else: return pd.Timedelta(days=0) df['Days'] = df.apply(calculate_days, axis=1) print(df)
方法3:使用df.loc索引赋值
通过布尔索引分别对不同状态的行赋值,逻辑清晰直观:
import pandas as pd from datetime import date data={'Status':['Sold', 'Active', 'Sold', 'Active'], 'Date': ['2024-10-02', '2024-05-06', '2024-11-01', '2024-07-12' ], } df=pd.DataFrame(data) today = pd.to_datetime(date.today()) df['Date']=pd.to_datetime(df['Date']) # 先初始化Days列为0天 df['Days'] = pd.Timedelta(days=0) # 为Active状态的行赋值日期差 df.loc[df['Status'] == 'Active', 'Days'] = df.loc[df['Status'] == 'Active', 'Date'] - today print(df)
内容的提问来源于stack exchange,提问作者slabbe
相关产品推荐
相关产品推荐

