J'ai un cadre de données de pandas qui ressemble à ceci (c'est un assez gros)
date exer exp ifor mat
1092 2014-03-17 American M 528.205 2014-04-19
1093 2014-03-17 American M 528.205 2014-04-19
1094 2014-03-17 American M 528.205 2014-04-19
1095 2014-03-17 American M 528.205 2014-04-19
1096 2014-03-17 American M 528.205 2014-05-17
maintenant, je voudrais parcourir ligne par ligne et au fur et à mesure que je parcourais chaque ligne, la valeur de ifor
in dans chaque ligne peut changer en fonction de certaines conditions et j'ai besoin de rechercher un autre cadre de données.
Maintenant, comment puis-je mettre à jour ceci pendant que j'itère .. Essayé quelques choses qu'aucune d'entre elles n'a fonctionné.
for i, row in df.iterrows():
if <something>:
row['ifor'] = x
else:
row['ifor'] = y
df.ix[i]['ifor'] = x
Aucune de ces approches ne semble fonctionner. Je ne vois pas les valeurs mises à jour dans le cadre de données.
Vous pouvez affecter des valeurs à la boucle en utilisant df.set_value:
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.set_value(i,'ifor',ifor_val)
si vous n'avez pas besoin des valeurs de ligne, vous pouvez simplement parcourir les indices de df, mais j'ai conservé la boucle for originale au cas où vous auriez besoin de la valeur de la ligne pour quelque chose qui ne figure pas ici.
mettre à jour
df.set_value () est obsolète depuis la version 0.21.0Vous pouvez utiliser df.at () à la place:
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.at[i,'ifor'] = ifor_val
L'objet Pandas DataFrame doit être considéré comme une série de séries. En d'autres termes, vous devriez y penser en termes de colonnes. Cela est important parce que, lorsque vous utilisez pd.DataFrame.iterrows
, vous parcourez les lignes en tant que série. Mais il s’agit de non la série que le bloc de données est en train de stocker. Il s’agit donc de nouvelles séries créées pour vous pendant l’itération. Cela implique que lorsque vous tentez de les affecter, ces modifications ne seront pas répercutées dans le bloc de données d'origine.
Ok, maintenant que c'est hors de propos: que faisons-nous?
Les suggestions antérieures à ce poste incluent:
pd.DataFrame.set_value
est obsolète à partir de Pandas version 0.21pd.DataFrame.ix
est obsolètepd.DataFrame.loc
c'est bien mais peut fonctionner sur les indexeurs de tableaux et vous pouvez faire mieuxMa recommandation
Utilisez pd.DataFrame.at
for i in df.index:
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
Vous pouvez même changer ceci en:
for i in df.index:
df.at[i, 'ifor'] = x if <something> else y
et si je dois utiliser la valeur de la ligne précédente pour la condition if?
for i in range(1, len(df) + 1):
j = df.columns.get_loc('ifor')
if <something>:
df.iat[i - 1, j] = x
else:
df.iat[i - 1, j] = y
Vous devez attribuer une valeur par df.ix[i, 'exp']=X
ou df.loc[i, 'exp']=X
au lieu de df.ix[i]['ifor'] = x
.
Sinon, vous travaillez sur une vue et vous devriez obtenir un réchauffement:
-c:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
Mais il est certain que la boucle devrait probablement être mieux remplacée par un algorithme vectorisé pour tirer le meilleur parti de DataFrame
comme l'a suggéré @Phillip Cloud.
Une méthode que vous pouvez utiliser est itertuples()
, qui effectue une itération sur les lignes DataFrame en tant qu'attributs nommés, avec la valeur d'index comme premier élément du Tuple. Et c'est beaucoup plus rapide que iterrows()
. Pour itertuples()
, chaque row
contient sa Index
dans le DataFrame, et vous pouvez utiliser loc
pour définir la valeur.
for row in df.itertuples():
if <something>:
df.at[row.Index, 'ifor'] = x
else:
df.at[row.Index, 'ifor'] = x
df.loc[row.Index, 'ifor'] = x
Merci @SantiStSupery, utiliser .at
est beaucoup plus rapide .
Eh bien, si vous voulez de toute façon itérer, pourquoi ne pas utiliser la méthode la plus simple, df['Column'].values[i]
df['Column'] = ''
for i in range(len(df)):
df['Column'].values[i] = something/update/new_value
Ou si vous souhaitez comparer les nouvelles valeurs avec les anciennes ou quelque chose du genre, pourquoi ne pas les stocker dans une liste et les ajouter à la fin.
mylist, df['Column'] = [], ''
for <condition>:
mylist.append(something/update/new_value)
df['Column'] = mylist
for i, row in df.iterrows():
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
Incrémente le nombre MAX d'une colonne. Par exemple :
df1 = [sort_ID, Column1,Column2]
print(df1)
Ma sortie:
Sort_ID Column1 Column2
12 a e
45 b f
65 c g
78 d h
MAX = df1['Sort_ID'].max() #This returns my Max Number
Maintenant, je dois créer une colonne dans df2 et remplir les valeurs de colonne qui incrémentent le MAX.
Sort_ID Column1 Column2
79 a1 e1
80 b1 f1
81 c1 g1
82 d1 h1
Remarque: df2 ne contiendra initialement que Column1 et Column2. nous avons besoin de la colonne Sortid pour être créée et incrémentielle du MAX de df1.