给pandas DataFrame的切片赋值
我正在尝试为任何给定的日期计算一个有效日期。这个数据框中有一列是通过 BMonthEnd 计算出来的,这个 BMonthEnd 是指考虑到假期的每个月最后一个工作日(具体的计算代码这里没有展示)。
下面显示的部分数据框中,EffectiveDate 列的值和 Date 列的值是相同的,这是第一步的结果。
Date BMonthEnd EffectiveDate
2014-08-24 2014-08-24 2014-08-29 2014-08-24
2014-08-25 2014-08-25 2014-08-29 2014-08-25
2014-08-26 2014-08-26 2014-08-29 2014-08-26
2014-08-27 2014-08-27 2014-08-29 2014-08-27
2014-08-28 2014-08-28 2014-08-29 2014-08-28
2014-08-29 2014-08-29 2014-08-29 2014-08-29
2014-08-30 2014-08-30 2014-08-29 2014-08-30
2014-08-31 2014-08-31 2014-08-29 2014-08-31
现在我尝试用以下方法选出需要更改的数据:
df[~(df.Date<df.BMonthEnd)].EffectiveDate # giving the expected slice
# but
df[~(df.Date<df.BMonthEnd)].EffectiveDate = 1
# gives error
SettingWithCopyWarning: A value is trying to be set on a copy of a slice
from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
self[name] = value
在收到警告后,我尝试了另一种方法:
df.loc[~(df.Date<df.BMonthEnd)].EffectiveDate = 1
但这也出现了同样的错误。(注意,这里赋值时用的 1 只是另一个函数的占位符)而且这个赋值并没有反映在原始的数据框上。我明白我实际上是在给一个副本赋值,所以这并没有按照预期改变原始的数据框。
那么,我该如何使用选择语法来进行赋值呢?我真的不想一个一个地遍历数据框。
1 个回答
1
我搞明白了。选择数据框中的某一列(Series)实际上让我可以同时对这列和原始数据框进行赋值。这让我可以使用切片语法来应用一些逻辑,从而影响结果:
# not all methods, classes shown
def effective_date(dr):
df = pd.DataFrame(dr, index=dr, columns=['Date'])
df['BMonthEnd'] = df.Date.apply(h.last_business_day)
df['MonthEnd'] = df.Date.apply(h.month_end)
df['EffectiveDate'] = df.Date
# df.EffectiveDate[~(df.Date<df.BMonthEnd)] = df.MonthEnd
df.loc[~(df.Date<df.BMonthEnd),'EffectiveDate'] = df.MonthEnd
return df.EffectiveDate
我根据Jeff的建议更新了内容。现在明白了为什么链式索引会让你陷入麻烦。我做了一些时间测试,结果似乎更快,但在给数据框赋值时,使用.loc方法是更好的选择。