在创建新列时以及在删除NaN行时设置withCopy

时间:2017-04-02 06:22:37

标签: python python-3.x pandas chained-assignment

我一直在四处寻找pandas docs here,并在herehere周围发布的问题中尝试不同的代码行,我似乎无法通过复制警告远离设置。我更愿意学习编码"对"方式而不仅仅是ignoring the warnings.

以下几行代码都在for循环中,我不想多次生成此警告,因为它可能会减慢速度。

我试图创建一个名为的新列:' E' + vs其中vs是for循环列表中的字符串

但是对于他们中的每一个,我仍然得到以下警告,即使是最后3行:

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

以下是我迄今为止尝试过的麻烦事项:

#based on research, the first two seem to be the "wrong" way

df_out['E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out['E'+vs] = df_out[kvs].rolling(v).mean()

df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean().copy()
df_out.loc[:,'E'+vs] = df_out[kvs].rolling(v).mean()
df_out.loc[:,'E'+vs] = df_out.loc[:,kvs].rolling(v).mean()

另一个提供SettingWithCopyWarning的是:

df_out.dropna(inplace=True,axis=0)

这个也发出警告(但我认为这个会发出警告)

df_out = df_out.dropna(inplace=True,axis=0)

如何正确执行这两项操作?

编辑:这是产生原始df_out

的代码
df_out= pd.concat([vol.Date[1:-1], ret.Return_Time[:-2], vol.Freq_Time[:-2],
               vol.Freq_Time[:-1].shift(-1), vol.Freq_Time[:].shift(-2)],
               axis=1).dropna().set_index('Date')

2 个答案:

答案 0 :(得分:3)

这是一个令人困惑的话题。您发布的代码不是问题所在。这是您尚未发布的代码。它是生成df_out

的代码

考虑这个例子,并注意产生警告的最后一行。

df_other = pd.DataFrame(dict(A=[1], B=[2]))
df_out = df_other[:]

df_out['E'] = 5
//anaconda/envs/3.5/lib/python3.5/site-packages/ipykernel/__main__.py:4: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

现在我们尝试一个不会产生警告的同等事情

df_other = pd.DataFrame(dict(A=[1], B=[2]))
df_out = df_other.loc[:]

df_out['E'] = 5

然后

print `df_out`

   A  B  E
0  1  2  5

归结为大熊猫决定在数据框基于多种标准构建时附加is_copy属性。

注意

df_other[:].is_copy

<weakref at 0x103323458; to 'DataFrame' at 0x116a684e0>

df_other.loc[:].is_copy

返回None

那么什么类型的构造会触发复制?我仍然不知道一切,甚至我所知道的事情对我都没有意义。

为什么这不会触发呢?

df_other[['A', 'B', 'E']].is_copy

答案 1 :(得分:1)

首先,我不确定这是高效还是最佳方法。但是,当我向现有数据框添加新列时,我遇到了同样的问题,我决定使用reset_index方法。

这里我首先从EMPLOYEES列中删除Nan行,并将此操纵数据帧分配给新数据帧df1,然后将COMPANY_SIZE列添加到df1,如下所示:

df1 = all_merged_years.dropna(subset=['EMPLOYEES']).reset_index()

column = df1['EMPLOYEES']

Size =[]

df1['COMPANY_SIZE'] = ' '

for number in column:
    if number <=999:
        Size.append('Small')
    elif 999<number<=9999:
        Size.append('Medium')
    elif 9999<number:
        Size.append('Large')
    else:
        Size.append('UNKNOWN')

df1['COMPANY_SIZE'] = Size

这样我没有收到警告。希望有所帮助。