创建一个新列,但创建数据框的副本

时间:2020-05-08 21:27:40

标签: python pandas

我想检查上面一行的值,看它是否与当前行相同。我找到了一个很好的答案heredf['match'] = df.col1.eq(df.col1.shift())就是您正在比较的col1

但是,当我尝试时,收到了SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.警告。我的col1是一个字符串。我知道您可以禁止显示警告,但是如何检查上面的同一行并确保不创建数据框的副本?即使发出警告,我也确实获得了期望的输出,但是很好奇是否存在更好的方法。

import pandas as pd
data = {'col1':['a','a','a','b','b','c','c','c','d','d'],
       'week':[1,1,1,1,1,2,2,2,2,2]}
df = pd.DataFrame(data, columns=['col1','week'])
df['check_condition'] = 1
while sum(df.check_condition) != 0:
    for week in df.week:
        wk = df.loc[df.week == week]
        wk['match'] = wk.col1.eq(wk.col1.shift()) # <-- where the warning occurs
        # fix the repetitive value...which I have not done yet
        # for now just exit out of the while loop
        df.loc[df.week == week,'check_condition'] = 0

1 个答案:

答案 0 :(得分:1)

您不能忽略大熊猫SettingWithCopyWarning! 100%告诉您代码根本无法按预期运行。停止,调查并修复它。 (这不是您可以过滤掉的不可忽略的东西,就像熊猫关于折旧问题的FutureWarning一样。)

您的代码有多个问题:

  • 您正在尝试遍历一个数据帧(但不使用groupby()),对其进行切片(在子数据帧wk中,它是切片的副本)... < / li>
  • 然后将其分配给(不存在的)新列wk['match']。这很糟糕,您不应该这样做。 (您可以初始化df['match'] = np.nan,但是尝试在wk中分配给副本仍然是错误的)...
  • 尝试分配给SettingWithCopyWarning时,会触发
  • wk['match']。它告诉您wk是数据帧df的切片的副本,而不是df本身。因此,就像它告诉您的那样:A value is trying to be set on a copy of a slice from a DataFrame.只会在每次wk被循环覆盖时才丢弃该分配,因此即使您可以强制它在wk上工作,也是错误的。这就是SettingWithCopyWarning是代码气味的原因,因此您不应该首先复制df切片。
  • 稍后,您还尝试在df上进行迭代时分配给列df['check_condition'],这也很糟糕。

解决方案:

df['check_condition'] = df['col1'].eq(df['col1'].shift()).astype(int)

df
  col1  week  check_condition
0    a     1                0
1    a     1                1
2    a     1                1
3    b     1                0
4    b     1                1
5    c     2                0
6    c     2                1
7    c     2                1
8    d     2                0
9    d     2                1

通常,对于要根据某些分组条件遍历每组数据框的更复杂的代码,请改用groupby() and split-apply-combine

  • 您要按wk.col1.eq(wk.col1.shift())分组,即col1值与前一行不变的行
  • 并且您要将这些行上的check_condition设置为0
  • ,在col1值与前一行确实发生变化的行上为1

但是在这种简单的情况下,您可以跳过groupby()并直接进行分配。