Pandas 插值按组添加行,每个组的范围不同

Pandas interpolation adding rows by group with different ranges for each group

我正在尝试将行添加到 DataFrame 中,逐列插入值,并填充所有其他列。我的数据看起来像这样:

import pandas as pd 
import random

random.seed(42)
data = {'group':['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c' ],
        'value' : [1, 2, 5,  3, 4, 5, 7, 4, 7, 9],
        'other': random.sample(range(1, 100), 10)}

df = pd.DataFrame(data)
print(df)
  group  value  other
0     a      1     82
1     a      2     15
2     a      5      4
3     b      3     95
4     b      4     36
5     b      5     32
6     b      7     29
7     c      4     18
8     c      7     14
9     c      9     87

我想要实现的是这样的:

   group  value  other
      a      1     82
      a      2     15
      a      3     NaN
      a      4     NaN
      a      5     NaN
      b      3     95
      b      4     36
      b      5     32
      b      6     NaN
      b      7     29
      c      4     18
      c      5     NaN
      c      6     NaN
      c      7     14
      c      8     NaN
      c      9     87

例如,组 a 的范围是 1 到 5,b 的范围是 3 到 7,c 的范围是 4 到 9。

我遇到的问题是每个组都有不同的范围。我发现 something 假设所有组都有一个范围。这可以使用全局最小值和最大值并在每个组中删除额外的行,但由于我的数据相当大,因此每组添加很多行很快变得不可行。

>>> df.groupby('group').apply(lambda x: x.set_index('value').reindex(np.arange(x['value'].min(), x['value'].max() + 1))).drop(columns='group').reset_index()
   group  value  other
0      a      1   82.0
1      a      2   15.0
2      a      3    NaN
3      a      4    NaN
4      a      5    4.0
5      b      3   95.0
6      b      4   36.0
7      b      5   32.0
8      b      6    NaN
9      b      7   29.0
10     c      4   18.0
11     c      5    NaN
12     c      6    NaN
13     c      7   14.0
14     c      8    NaN
15     c      9   87.0

我们在 group 列上分组,然后用 value 列的最小值到最大值的范围重新索引每个组

一个选项是 complete function from pyjanitor,它有助于明确显示缺失的行(也有助于抽象重塑过程):

# pip install pyjanitor
import pandas as pd
import janitor

new_value = {'value' : lambda df: range(df.min(), df.max()+1)}

# expose the missing values per group via the `by` parameter
df.complete(new_value, by='group', sort = True)

   group  value  other
0      a      1   82.0
1      a      2   15.0
2      a      3    NaN
3      a      4    NaN
4      a      5    4.0
5      b      3   95.0
6      b      4   36.0
7      b      5   32.0
8      b      6    NaN
9      b      7   29.0
10     c      4   18.0
11     c      5    NaN
12     c      6    NaN
13     c      7   14.0
14     c      8    NaN
15     c      9   87.0