将值分配给pandas DataFrame的切片

7
我正在尝试确定任何给定日期的有效日期。数据框中有一列由BMonthEnd填充(考虑到节假日计算每月最后一个工作日 - 未在此处显示代码)。下面所示的部分数据框将EffectiveDate设置为第1步的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
使用 df.loc[row_indexer,col_indexer] = value,就像它所说的那样(你没有这样做)。 - Jeff
df.EffectiveDate[~(df.Date<df.BMonthEnd)] = 1 看起来是有效的。 - Joop
df['EffectiveDate'] 的 dtype 是什么? - unutbu
如果某天是本月的最后一个工作日,但不是本月的最后一天,那么生效日期将被设置为本月的最后一天。例如,在金融计算中确保最后一个工作日使用整个日历月...否则会有一些未计算的天数。 - Joop
Pandas的文档总体来说非常好,但是这个部分提供了一些有关返回数据视图和拷贝的方法的有用提示:http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copy - K Raphael
1个回答

1

我明白了。在Dataframe中选择Series,可以有效地对其进行赋值,并影响原始Dataframe。这使我能够使用切片语法来应用逻辑以影响结果:

# 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是更好的选择。


2
请使用以下代码:df.loc[~(df.Date<df.BMonthEnd),'EffectiveDate'] = df.MonthEnd,否则您将进行链式索引,请参阅此处:http://pandas-docs.github.io/pandas-docs-travis/indexing.html#indexing-view-versus-copy,这不能保证有效。 - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接