web-dev-qa-db-fra.com

Confusion concernant: pandas copie d'une tranche d'avertissement de trame de données

J'ai parcouru un tas de questions et réponses liées à ce problème, mais je trouve toujours que j'obtiens cette copie de l'avertissement de tranche dans des endroits où je ne m'y attendais pas. De plus, il surgit dans du code qui fonctionnait bien pour moi auparavant, ce qui m'amène à me demander si une sorte de mise à jour pourrait être le coupable.

Par exemple, il s'agit d'un ensemble de code où tout ce que je fais est de lire un fichier Excel dans un pandas DataFrame, et de réduire l'ensemble des colonnes incluses avec le Syntaxe df[[]].

 izmir = pd.read_Excel(filepath)
 izmir_lim = izmir[['Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60','MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5','MC_OLD_18>F>5',
               'MC_OLD_M_Child<5','MC_OLD_F_Child<5','MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery','Date to insert','Date of Entery']]

Maintenant, toute autre modification que j'apporte à ce fichier izmir_lim Déclenche la copie de l'avertissement de tranche.

izmir_lim['Age'] = izmir_lim.Age.fillna(0)
izmir_lim['Age'] = izmir_lim.Age.astype(int)

/Users/samlilienfeld/anaconda/lib/python3.5/site-packages/ipykernel/main.py:2: SettingWithCopyWarning: une valeur tente d'être définie sur une copie d'une tranche d'un DataFrame . Essayez d'utiliser .loc [row_indexer, col_indexer] = value à la place

Je suis confus parce que je pensais que le sous-ensemble de colonnes df[[]] Renvoyait une copie par défaut. Le seul moyen que j'ai trouvé pour supprimer les erreurs est d'ajouter explicitement df[[]].copy(). J'aurais pu jurer que dans le passé je n'avais pas à le faire et que je n'avais pas fait de copie d'erreur de tranche.

De même, j'ai un autre code qui exécute une fonction sur une trame de données pour la filtrer de certaines manières:

def lim(df):
if (geography == "All"):
    df_geo = df
else:
    df_geo = df[df.center_JO == geography]

df_date = df_geo[(df_geo.date_survey >= start_date) & (df_geo.date_survey <= end_date)]

return df_date

df_lim = lim(df)

À partir de ce moment, toutes les modifications que j'apporte à l'une des valeurs de df_lim Augmentent la copie de l'erreur de tranche. Le seul moyen de contourner ce problème que j'ai trouvé est de changer l'appel de fonction en:

df_lim = lim(df).copy()

Cela me semble juste mal. Qu'est-ce que je rate? Il semble que ces cas d'utilisation devraient renvoyer des copies par défaut, et j'aurais juré que la dernière fois que j'ai exécuté ces scripts, je ne rencontrais pas ces erreurs.
Dois-je simplement commencer à ajouter .copy() partout? Il semble qu'il devrait y avoir une façon plus propre de procéder. Toute idée ou aide est très appréciée.

18
Sam Lilienfeld
 izmir = pd.read_Excel(filepath)
 izmir_lim = izmir[['Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60',
                    'MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5',
                    'MC_OLD_18>F>5','MC_OLD_M_Child<5','MC_OLD_F_Child<5',
                    'MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery',
                    'Date to insert','Date of Entery']]

izmir_lim est une vue/copie de izmir. Vous essayez ensuite de lui attribuer. C'est ce qui lance l'erreur. Utilisez-le à la place:

 izmir_lim = izmir[['Gender','Age','MC_OLD_M>=60','MC_OLD_F>=60',
                    'MC_OLD_M>18','MC_OLD_F>18','MC_OLD_18>M>5',
                    'MC_OLD_18>F>5','MC_OLD_M_Child<5','MC_OLD_F_Child<5',
                    'MC_OLD_M>0<=1','MC_OLD_F>0<=1','Date to Delivery',
                    'Date to insert','Date of Entery']].copy()

Chaque fois que vous "créez" une nouvelle trame de données à partir d'une autre de la manière suivante:

new_df = old_df[list_of_columns_names]

new_df aura une valeur véridique dans son is_copy attribut. Lorsque vous essayez de lui attribuer, pandas lance le SettingWithCopyWarning.

new_df.iloc[0, 0] = 1  # Should throw an error

Vous pouvez surmonter cela de plusieurs manières.

Option 1

new_df = old_df[list_of_columns_names].copy()

Option # 2 (comme @ayhan l'a suggéré dans les commentaires)

new_df = old_df[list_of_columns_names]
new_df.is_copy = None

Option n ° 3

new_df = old_df.loc[:, list_of_columns_names]
18
piRSquared