逐行迭代时更新熊猫中的数据框
- 2025-02-28 08:24:00
- admin 原创
- 76
问题描述:
我有一个看起来像这样的熊猫数据框(它非常大)
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
现在我想逐行迭代,当我遍历每一行时,ifor
每行的值可能会根据某些条件而改变,我需要查找另一个数据框。
现在,我该如何在迭代过程中更新它。尝试了一些方法,但都不起作用。
for i, row in df.iterrows():
if <something>:
row['ifor'] = x
else:
row['ifor'] = y
df.ix[i]['ifor'] = x
这些方法似乎都不起作用。我没有看到数据框中更新的值。
解决方案 1:
您可以使用df.at
:
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.at[i,'ifor'] = ifor_val
对于 0.21.0 之前的版本,使用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)
如果您不需要行值,您可以简单地迭代索引df
,但我保留了原始的 for 循环,以防您需要这里未显示的行值。
解决方案 2:
Pandas DataFrame 对象应被视为一系列系列。换句话说,您应该从列的角度来考虑它。这很重要,因为当您使用时,pd.DataFrame.iterrows
您会将行作为系列进行迭代。但这些不是数据框存储的系列,因此它们是迭代时为您创建的新系列。这意味着当您尝试分配给它们时,这些编辑不会反映在原始数据框中。
好的,现在这个问题已经解决了:我们该做什么?
本文之前的建议包括:
pd.DataFrame.set_value
从 Pandas 0.21 版开始已弃用pd.DataFrame.ix
已弃用pd.DataFrame.loc
很好,但可以在数组索引器上工作,你可以做得更好
我的建议
使用pd.DataFrame.at
for i in df.index:
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
您甚至可以将其更改为:
for i in df.index:
df.at[i, 'ifor'] = x if <something> else y
回复评论
如果我需要将前一行的值用于 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
解决方案 3:
您可以使用的方法是itertuples()
,它以命名元组的形式迭代 DataFrame 行,索引值作为元组的第一个元素。与相比,它要快得多iterrows()
。对于itertuples()
,每个都row
包含Index
在 DataFrame 中,您可以使用loc
来设置值。
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
大多数情况下,itertuples()
比iat
或更快at
。
感谢@SantiStSupery,使用.at
比快得多loc
。
解决方案 4:
最好使用lambda
以下函数df.apply()
-
df["ifor"] = df.apply(lambda x: {value} if {condition} else x["ifor"], axis=1)
解决方案 5:
您应该通过df.ix[i, 'exp']=X
或df.loc[i, 'exp']=X
而不是 来分配值df.ix[i]['ifor'] = x
。
否则,您正在处理一个视图,并且应该得到一个预热:
`-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`
但可以肯定的是,循环最好被一些矢量化算法所取代,以充分利用DataFrame
@Phillip Cloud 所建议的功能。
解决方案 6:
好吧,如果你无论如何都要进行迭代,为什么不使用最简单的方法呢?df['Column'].values[i]
df['Column'] = ''
for i in range(len(df)):
df['Column'].values[i] = something/update/new_value
或者,如果您想将新值与旧值或类似内容进行比较,为什么不将其存储在列表中然后附加在最后。
mylist, df['Column'] = [], ''
for <condition>:
mylist.append(something/update/new_value)
df['Column'] = mylist
解决方案 7:
for i, row in df.iterrows():
if <something>:
df.at[i, 'ifor'] = x
else:
df.at[i, 'ifor'] = y
解决方案 8:
列表理解可能是一种选择。
df['new_column'] = [your_func(x) for x in df['column']]
这将遍历列 df['column'],使用 df['column'] 中的值调用函数 your_func,并为新列 df['new_column'] 中的行分配一个值。
请不要忘记创建一个函数。
解决方案 9:
从列中增加 MAX 数字。例如:
df1 = [sort_ID, Column1,Column2]
print(df1)
我的输出:
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
现在,我需要在 df2 中创建一个列并填充增加 MAX 的列值。
Sort_ID Column1 Column2
79 a1 e1
80 b1 f1
81 c1 g1
82 d1 h1
注意:df2 最初只包含 Column1 和 Column2。我们需要创建 Sortid 列并从 df1 中增加 MAX。
扫码咨询,免费领取项目管理大礼包!