熊猫在 groupby 内插值

Posted

技术标签:

【中文标题】熊猫在 groupby 内插值【英文标题】:Pandas interpolate within a groupby 【发布时间】:2016-08-31 15:07:42 【问题描述】:

我有一个包含以下信息的数据框:

    filename    val1    val2
t                   
1   file1.csv   5       10
2   file1.csv   NaN     NaN
3   file1.csv   15      20
6   file2.csv   NaN     NaN
7   file2.csv   10      20
8   file2.csv   12      15

我想根据索引插入数据框中的值,但仅限于每个文件组内

为了插值,我通常会这样做

df = df.interpolate(method="index")

要分组,我愿意

grouped = df.groupby("filename")

我希望内插数据框看起来像这样:

    filename    val1    val2
t                   
1   file1.csv   5       10
2   file1.csv   10      15
3   file1.csv   15      20
6   file2.csv   NaN     NaN
7   file2.csv   10      20
8   file2.csv   12      15

NaN 在 t = 6 时仍然存在,因为它们是 file2 组中的第一项。

我怀疑我需要使用“apply”,但无法弄清楚具体如何...

grouped.apply(interp1d)
...
TypeError: __init__() takes at least 3 arguments (2 given)

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:
>>> df.groupby('filename').apply(lambda group: group.interpolate(method='index'))
    filename  val1  val2
t                       
1  file1.csv     5    10
2  file1.csv    10    15
3  file1.csv    15    20
6  file2.csv   NaN   NaN
7  file2.csv    10    20
8  file2.csv    12    15

【讨论】:

这似乎适用于小型数据帧,但在大型数据帧上需要 long 时间(比使用 .interpolate() 的时间长几个数量级)。你会期望效率会差很多吗?与行数相比,组的数量很小(大约 1000 个组与 10^7 行相比)。【参考方案2】:

我也遇到了这个问题。除了使用apply,您还可以使用transform,如果您有大约 1000 个组,这将使您的运行时间减少 25% 以上:

import numpy as np
import pandas as pd

np.random.seed(500)
test_df = pd.DataFrame(
    'a': np.random.randint(low=0, high=1000, size=10000),
    'b': np.random.choice([1, 2, 4, 7, np.nan], size=10000, p=([0.2475]*4 + [0.01]))
)

测试:

%timeit test_df.groupby('a').transform(pd.DataFrame.interpolate)

输出:566 ms ± 27.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.groupby('a').apply(pd.DataFrame.interpolate)

输出:788 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.groupby('a').apply(lambda group: group.interpolate())

输出:787 ms ± 17.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit test_df.interpolate()

输出:918 µs ± 16.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

与在完整 DataFrame 上对 interpolate 的完全矢量化调用相比,您仍然会看到运行时间显着增加,但我认为您在 pandas 中不能做得更好。

【讨论】:

您使用transform 的解决方案没有提供所需的输出。 也许这是因为它比原始帖子晚了大约 4 年,但我得到了相反的结果。 apply 更快【参考方案3】:

考虑到上述方法运行时间较长,我建议使用for循环和interpolate(),代码不超过几行,但速度要快得多。

for i in range(len(df.filename.unique())):
      mask = df.loc[:,'filename']==df.filename.unique()[i]
      df[mask]=dfs[mask].interpolate(method='index')

【讨论】:

我刚刚比较了 groupby 方法和 for 循环方法,它们实际上在 130 个组的 6000 行 DataFrame 上似乎具有相似的性能。我承认,我的两个插值都是在线性方法上运行的。

以上是关于熊猫在 groupby 内插值的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用带有应用功能的熊猫 groupby 来解决副作用? (第一组申请两次)

熊猫:在 groupby 'date' 中删除重复项

如何在复杂的熊猫 groupby 中绘制图形?

熊猫:GroupBy .pipe() 与 .apply()

在 groupby 熊猫对象上应用 rolling() 时,多索引重复

groupby - python 熊猫数据框