簡體   English   中英

SettingWithCopyWarning 即使使用.loc[row_indexer,col_indexer] = value

[英]SettingWithCopyWarning even when using .loc[row_indexer,col_indexer] = value

這是我獲得SettingWithCopyWarning的代碼行之一:

value1['Total Population']=value1['Total Population'].replace(to_replace='*', value=4)

然后我改為:

row_index= value1['Total Population']=='*'
value1.loc[row_index,'Total Population'] = 4

這仍然給出相同的警告。 我該如何擺脫它?

另外,對於我使用過的convert_objects(convert_numeric=True) function,我收到了相同的警告,有什么辦法可以避免這種情況。

 value1['Total Population'] = value1['Total Population'].astype(str).convert_objects(convert_numeric=True)

這是我收到的警告消息:

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 the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 

如果您使用.loc[row,column]並仍然得到相同的錯誤,則可能是因為復制了另一個數據框。 你必須使用.copy()

這是一步一步的錯誤再現:

import pandas as pd

d = {'col1': [1, 2, 3, 4], 'col2': [3, 4, 5, 6]}
df = pd.DataFrame(data=d)
df
#   col1    col2
#0  1   3
#1  2   4
#2  3   5
#3  4   6

創建一個新列並更新其值:

df['new_column'] = None
df.loc[0, 'new_column'] = 100
df
#   col1    col2    new_column
#0  1   3   100
#1  2   4   None
#2  3   5   None
#3  4   6   None

我沒有收到錯誤。 但是,讓我們根據前一個數據框創建另一個數據框:

new_df = df.loc[df.col1>2]
new_df
#col1   col2    new_column
#2  3   5   None
#3  4   6   None

現在,使用.loc ,我將嘗試以相同的方式替換一些值:

new_df.loc[2, 'new_column'] = 100

但是,我再次收到了這個可惡的警告:

試圖在來自 DataFrame 的切片副本上設置值。 嘗試使用 .loc[row_indexer,col_indexer] = value 代替

請參閱文檔中的警告: https : //pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

解決方案

在創建新數據框時使用.copy()將解決警告:

new_df_copy = df.loc[df.col1>2].copy()
new_df_copy.loc[2, 'new_column'] = 100

現在,您將不會收到任何警告!

如果您的數據框是使用另一個數據框頂部的過濾器創建的,請始終使用.copy()

您是否嘗試過直接設置?:

value1.loc[value1['Total Population'] == '*', 'Total Population'] = 4

我來這里是因為我想根據另一列中的值有條件地設置新列的值。

對我有用的是 numpy.where:

import numpy as np
import pandas as pd
...

df['Size'] = np.where((df.value > 10), "Greater than 10", df.value)

numpy docs ,這相當於:

[xv if c else yv
 for c, xv, yv in zip(condition, x, y)]

這是 zip 的一個很好的用法......

我不知道這對數據存儲/內存的影響有多糟糕,但它每次都會為您的平均數據幀修復它:

def addCrazyColFunc(df):
    dfNew = df.copy()
    dfNew['newCol'] = 'crazy'
    return dfNew

就像消息說的那樣......制作一份副本,你就可以開始了。 請如果有人可以在沒有副本的情況下解決上述問題,請發表評論。 上面所有的 loc 東西都不適用於這種情況。

嘗試在發出警告的行之前添加以下內容(如有必要:重新索引)。 它與df.copy()具有相同的效果,因此不會有警告。

 df = df.reset_index(drop=True) 

得到了解決方案:

我創建了一個新的 DataFrame 並僅存儲了我需要處理的列的值,現在它沒有給我任何錯誤!

奇怪,但有效。

指定它是為我工作的副本。 我剛剛在語句的末尾添加了.copy()

value1['Total Population'] = value1['Total Population'].replace(to_replace='*', value=4).copy()

這應該可以解決您的問題:

value1[:, 'Total Population'] = value1[:, 'Total Population'].replace(to_replace='*', value=4)

我能夠避免使用以下語法出現相同的警告消息:

value1.loc[:, 'Total Population'].replace('*', 4)

請注意,不需要將數據幀重新分配給自身,即 value1['Total Population']=value1['Total Population']...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM