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

问题描述 投票:0回答:1

我想检查上面一行的值,并看到它与当前行相同。我找到了一个很好的答案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
python pandas
1个回答
0
投票

您不能忽略熊猫SettingWithCopyWarning!100%告诉您代码根本无法按预期运行。停止,调查并修复它。 (这不是您可以过滤掉的不可忽略的事情,就像FutureWarning关于弃用的na。)

在您的情况下,它是在wk上触发的,这是来自数据帧df的切片,而不是实际数据帧。它告诉您A value is trying to be set on a copy of a slice from a DataFrame.

因此,为了解决这个问题,让我们退后一步,弄清楚您的代码正在尝试重写什么。

您正在尝试遍历一个数据帧,对其进行切片(在子数据帧wk中,是副本),然后分配给不存在的新列wk['match']。这很糟糕,您不应该这样做。稍后,您还尝试在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

通常,对于要遍历数据帧组的更复杂的代码,应使用split-apply-combine代替。

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

但是实际上,在这种情况下,您可以跳过groupby()并直接分配。

© www.soinside.com 2019 - 2024. All rights reserved.