【问题标题】:What is the correct way of doing the same operation over multiple pandas dataframes?对多个熊猫数据框执行相同操作的正确方法是什么?
【发布时间】:2020-01-29 08:09:22
【问题描述】:

我正在尝试:

  1. 检查某个范围内的值是否存在于数据框中
  2. 如果不是,则添加值并进行插值。

参考this answer,我已经检查过它是否适用于单个数据帧。例如:

# Original dataframe

    code    ratio
...
5   5.0     1.649561
6   6.0     1.466403
7   11.0    1.696970
8   12.0    1.646259

# Code to add row + interpolate
for i in range(5, 13):
    if i not in df.values:
        df.loc[-1, 'code'] = i
        df = df.sort_values('code').reset_index(drop=True)
        df = df.interpolate()

# Result
code        ratio
0   5.0     1.649561
1   6.0     1.466403
2   7.0     1.581686
3   8.0     1.639328
4   9.0     1.668149
5   10.0    1.682559
6   11.0    1.696970
7   12.0    1.646259

检查它是否适用于单个数据帧,我希望它可以在我拥有的多个数据帧上完成。所以我尝试了以下代码,使用数据框列表进行迭代:

for df in [df1, df2, df3...]:
    for i in range(5, 13):
        if i not in df.values:
            df.loc[-1, 'code'] = i
            df = df.sort_values('code').reset_index(drop=True)
            df = df.interpolate()

然后即使对于之前工作的数据框,它也会返回:

code        ratio
5   5.0     1.649561
6   6.0     1.466403
7   11.0    1.696970
8   12.0    1.646259
-1  7.0     NaN

这显然不是我想要的结果。

造成这种差异的原因是什么? 使用多个数据帧的列表进行迭代是否是一种错误的方法?

【问题讨论】:

  • 我建议在迭代修改 DataFrame 时最好使用 dict - 使用键 df1, df2....
  • 使用for name, df in df_dict.items(): 进行迭代,并使用df_dict[name] = df 进行分配似乎效果不佳:(
  • 解压回原来的变量名怎么样....所以在我建议的循环之后,最后一行将是df1, df2, df3 = df_list
  • 更好的方法是dict - imho :)

标签: python pandas dataframe


【解决方案1】:

您需要重新分配到列表中,然后解包,例如:

df_list = [df1, df2, df3...]
for i, df in enumerate(df_list):
    for j in range(5, 13):
        if j not in df.values:
            df.loc[-1, 'code'] = j
            df = df.sort_values('code').reset_index(drop=True)
            df = df.interpolate()
    df_list[i] = df

#Unpack back to original variables
df1, df2, df3, ... = df_list

【讨论】:

  • 我建议使用 dict 作为带有键 df1df2... 而不是 list 的 DataFrame 的容器
  • 对不起,它似乎不起作用。说df1 是我主要检查的数据框,在使用您的代码并再次使用df1 进行检查后,我的问题仍然得到不需要的结果。即使将df.loc[-1, 'code'] = i 更改为df.loc[-1, 'code'] = j
  • 是的,如果你使用列表,它不会改变那个变量,但它会改变df_list[0] - 这就是为什么最好使用字典df_dict = {'df1': ...},然后你可以迭代并更新值并使用df_dict['df1'] 返回
  • 好的,这将需要对整个代码进行一些更改......但会尝试。即使它有效,我也无法按原样接受您的答案。
【解决方案2】:

您可以使用inplace=True 直接修改列表中的每个数据框。由于数据帧列表是每个数据帧的浅表副本,因此对它们的任何修改都会影响原始数据帧。但是,此方法不允许链接方法,因此您需要使用 inplace=True 将链命令分解为单独的方法调用。此方法利用列表创建数据帧的浅拷贝

Sample dataframes

In [153]: df1
Out[153]:
   code     ratio
0   5.0  1.649561
1   6.0  1.466403
2  11.0  1.696970
3  12.0  1.646259

In [155]: df2
Out[155]:
   code     ratio
0   5.0  1.649561
1   6.0  1.466403
2  11.0  1.696970
3  19.0  1.646259

dfs = [df1, df2]

for df in dfs:
    for i in range(5, 13):
        if i not in df.values:
            df.loc[-1, 'code'] = i
            df.sort_values('code', inplace=True)
            df.reset_index(drop=True, inplace=True)
            df.interpolate(inplace=True)

输出

In [168]: df1
Out[168]:
   code     ratio
0   5.0  1.649561
1   6.0  1.466403
2   7.0  1.581686
3   8.0  1.639328
4   9.0  1.668149
5  10.0  1.682560
6  11.0  1.696970
7  12.0  1.646259

In [169]: df2
Out[169]:
   code     ratio
0   5.0  1.649561
1   6.0  1.466403
2   7.0  1.581686
3   8.0  1.639328
4   9.0  1.668149
5  10.0  1.682560
6  11.0  1.696970
7  12.0  1.671615
8  19.0  1.646259

注意:这个解决方案只是为了证明它在这个特定问题上是可行的。在更复杂的问题上,由于某些命令不支持inplace 而Pandas 正在弃用inplace 选项,因此它不可行。

【讨论】:

    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 2013-12-24
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2021-08-23
    • 2012-10-15
    相关资源
    最近更新 更多