给pandas DataFrame的切片赋值

7 投票
1 回答
5878 浏览
提问于 2025-04-18 05:59

我正在尝试为任何给定的日期计算一个有效日期。这个数据框中有一列是通过 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方法是更好的选择。

撰写回答