Pandas在groupby内插入

时间:2016-05-05 17:55:33

标签: python pandas group-by interpolation

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

    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组中的第一项。

我怀疑我需要使用"申请"但是还没有能够弄清楚到底是怎么...

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

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:8)

>>> 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

答案 1 :(得分:1)

我也碰到了这个。您可以使用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)

与完整数据框架上interpolate的完全向量化调用相比,您仍会看到运行时间显着增加,但我不认为您可以在pandas中做得更好。

答案 2 :(得分:0)

考虑到上述方法的运行时间较长,我建议使用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')