1
resposta

Pandas SettingWithCopyWaning

Olá. Quando tento criar uma nova no pandas recebo o seguinte Warning

/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:5: 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: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy """

O código que gera o warning está a seguir. Fui na doc indicada mas não consegui acertar para o warning desaparecer.

  dataset = pd.read_csv('/kaggle/input/home-data-for-ml-course/train.csv')

columns = ['LotArea','Street', 'MSZoning']

s_dataset = dataset[columns]

answer = dataset.SalePrice

s_dataset['Street'] = s_dataset['Street'].map({'Pave':1, 'Grvl':2})
1 resposta

Olá, Yves, tudo bem?

O SettingwithCopyWarningé um tipo de warning em que o Pandas detecta que o usuário está fazendo uma alteração em um dado DataFrame e essa alteração refletirá também em um anterior.

Para ficar mais claro, supomos que o dataset é nosso df1 e o s_dataset é nosso df2 das imagens abaixo. Quando você faz apenas s_dataset = dataset[columns] você cria apenas uma cópia rasa (visualização do dataframe - view), ou seja, quando algo é alterado em um, o outro se altera também e por isso levanta-se esse warning.

 

Imagem divida em duas partes. A primeira parte à esquerda tem um texto escrito View e abaixo um Dataframe azul chamado de df1 com dimensão (3x3) preenchido com alguns números. Dentro dele um Dataframe com dimensão (2x2) chamado de df2, evidenciando que df2 é uma view (ou cópia rasa) de df1. A segunda parte à direita da imagem tem um texto escrito Copy e abaixo um Dataframe azul chamado de df1 com dimensão (3x3) preenchido com alguns números e lado a lado  tem um Dataframe com dimensão (2x2) chamado de df2, mostrando que nesse caso df2 é uma cópia profunda e independente de df1.

 

Como pode ser visto acima, o view df2(s_dataset) à esquerda é apenas um subset do original df1(dataset), diferentemente da cópia profunda a direita em que cria um objeto único df2(s_dataset) separado do df1(dataset). O caso à esquerda pode gerar problemas quando tentamos fazer alterações em um dos DataFrames, como podemos ver na imagem abaixo:

 

Imagem divida em duas partes. A primeira parte à esquerda tem um texto escrito Modifying a View e abaixo um Dataframe azul chamado de df1 com dimensão (3x3) preenchido com alguns números e com um dos números em branco para simbolizar que foi modificado. Dentro dele um Dataframe com dimensão (2x2) chamado de df2, que também engloba esse número modificado, evidenciando em uma view temos a alteração atingida nos dois Dataframes. A segunda parte à direita da imagem tem um texto escrito Copy e abaixo um Dataframe azul chamado de df1 com dimensão (3x3) preenchido com alguns números e lado a lado tem um Dataframe com dimensão (2x2) chamado de df2 onde apenas nele um dos números foi alterado, evidenciando que nesse caso df2 é o único a sofrer a alteração desejada por ser independente de df1.

 

Se, por exemplo, quisermos modificar apenas o df1 ou o df2 o caso à esquerda não seria adequado e por isso, o warning é apresentado.

Mas, como queremos modificar apenas o s_dataset(como na direita das imagens) é necessário fazer uma cópia profunda (copy) do dataframe original. Assim, existem algumas formas de se atingir o resultado esperado, duas delas são:

s_dataset = dataset[columns].copy()

Ou então, como sugerido no aviso, podemos utilizar o loc:

s_dataset = dataset.loc[:, columns]

Assim, nosso código ficaria da seguinte maneira:

dataset = pd.read_csv('train.csv')

columns = ['LotArea','Street', 'MSZoning']

s_dataset = dataset.loc[:, columns]
# ou s_dataset = dataset[columns].copy()

answer = dataset.SalePrice

s_dataset['Street'] = s_dataset['Street'].map({'Pave':1, 'Grvl':2})

s_dataset

Com a saída da seguinte maneira:

    LotArea    Street    MSZoning
0    8450    1    RL
1    9600    1    RL
2    11250    1    RL
3    9550    1    RL
4    14260    1    RL
...    ...    ...    ...
1455    7917    1    RL
1456    13175    1    RL
1457    9042    1    RL
1458    9717    1    RL
1459    9937    1    RL
1460 rows × 3 columns

Para entender um pouco mais do warning e aprofundar-se nesse tipo de situação, deixarei na tabela abaixo as documentações que utilizamos para explicar estes comportamentos:

Para Saber Mais
SettingwithCopyWarning: Como corrigir este warning em Pandas
Retornando uma view x uma cópia
Como lidar com o SettingwithCopyWarning em Pandas

Qualquer dúvida é só chamar!

Forte abraço!