如何在pandas中插入和填充计算值行?

3z6pesqy  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(142)

我有一个pandas dataframe,缺少theta步骤,如下所示,

index  name theta r
1      wind 0     10
2      wind 30    17
3      wind 60    19
4      wind 90    14
5      wind 120   17
6      wind 210   18
7      wind 240   17
8      wind 270   11
9      wind 300   13

我需要把缺失的theta加上值

index  name theta r
1      wind 0     10
2      wind 30    17
3      wind 60    19
4      wind 90    14
5      wind 120   17
6      wind 150   null
7      wind 180   null
8      wind 210   18
9      wind 240   17
10     wind 270   11
11     wind 300   13
12     wind 330   null

然后用线性插值填充空值。为了简单起见,这里我们可以考虑前一个和下一个可用值的平均值,

index  name theta r
1      wind 0     10
2      wind 30    17
3      wind 60    19
4      wind 90    14
5      wind 120   17
6      wind 150   17.5 #(17 + 18)/2
7      wind 180   17.5 #(17 + 18)/2
8      wind 210   18
9      wind 240   17
10     wind 270   11
11     wind 300   13
12     wind 330   11.5 #(13 + 10)/2

我该怎么做?

bjg7j2ky

bjg7j2ky1#

可以使用interpolateffill

out = (
 df.set_index('theta').reindex(range(0, 330+1, 30))
   .interpolate().ffill().reset_index()[df.columns]
)

输出:

name  theta          r
0   wind      0  10.000000
1   wind     30  17.000000
2   wind     60  19.000000
3   wind     90  14.000000
4   wind    120  17.000000
5   wind    150  17.333333
6   wind    180  17.666667
7   wind    210  18.000000
8   wind    240  17.000000
9   wind    270  11.000000
10  wind    300  13.000000
11  wind    330  13.000000

执行循环插值时,只能用limit_area='inside'填充内部值,然后用第一个和最后一个有效行的平均值填充fillna

out = (
 df.set_index('theta').reindex(range(0, 330+1, 30))
   .interpolate(method='linear', limit_area='inside')
   .pipe(lambda d: d.fillna(d.dropna().iloc[[0, -1]].select_dtypes('number').mean()))
   .ffill().reset_index()[df.columns]
)

输出:

name  theta          r
0   wind      0  10.000000
1   wind     30  17.000000
2   wind     60  19.000000
3   wind     90  14.000000
4   wind    120  17.000000
5   wind    150  17.333333
6   wind    180  17.666667
7   wind    210  18.000000
8   wind    240  17.000000
9   wind    270  11.000000
10  wind    300  13.000000
11  wind    330  11.500000

如果你真的希望多个中间值相同,另一个选择是自己计算平均值(使用ffill/bfill):

tmp = df.set_index('theta').reindex(range(0, 330+1, 30))
tmp2 = tmp.ffill()

out = ((tmp2+tmp.bfill().fillna(df.iloc[0]))
       .select_dtypes('number').div(2)
       .combine_first(tmp2).reset_index()[df.columns]
      )

输出:

name  theta     r
0   wind      0  10.0
1   wind     30  17.0
2   wind     60  19.0
3   wind     90  14.0
4   wind    120  17.0
5   wind    150  17.5  # same values
6   wind    180  17.5  #
7   wind    210  18.0
8   wind    240  17.0
9   wind    270  11.0
10  wind    300  13.0
11  wind    330  11.5
  • 注:这些方法应该适用于任何数量的数值列(不仅仅是'r')。

使用组

一个简单的方法是使用函数和groupby.apply

def interp(df):
    return  (
 df.set_index('theta').reindex(range(0, 330+1, 30))
   .interpolate(method='linear', limit_area='inside')
   .pipe(lambda d: d.fillna(d.dropna().iloc[[0, -1]].select_dtypes('number').mean()))
   .ffill().reset_index()[df.columns]
)

out = df.groupby('name', group_keys=False).apply(interp)

或者,首先pivot您的数据:

out = (
 df.pivot(index='theta', columns='name')
   .reindex(range(0, 330+1, 30))
   .interpolate(method='linear', limit_area='inside')
   .pipe(lambda d: d.fillna(d.dropna().iloc[[0, -1]].select_dtypes('number').mean()))
   .ffill().stack().reset_index()[df.columns]
)

示例输出(#显示最初缺失的值):

name  theta           r
0   turb      0  100.000000
1   turb     30  170.000000
2   turb     60  190.000000
3   turb     90  140.000000
4   turb    120  170.000000
5   turb    150  173.333333  #
6   turb    180  176.666667  #
7   turb    210  180.000000
8   turb    240  170.000000
9   turb    270  110.000000
10  turb    300  130.000000
11  turb    330  115.000000  #
0   wind      0   10.000000
1   wind     30   17.000000
2   wind     60   19.000000
3   wind     90   14.000000
4   wind    120   17.000000  #
5   wind    150   17.333333  #
6   wind    180   17.666667
7   wind    210   18.000000
8   wind    240   17.000000
9   wind    270   11.000000
10  wind    300   13.000000
11  wind    330   11.500000  #

使用bfill/ffill

tmp = (df.set_index(['name', 'theta'])
         .reindex(pd.MultiIndex.from_product([df['name'].unique(), range(0, 330+1, 30)],
                                             names=['name', 'theta']
                                            ))
      )
tmp2 = tmp.groupby(level='name').ffill()

out = ((tmp2+tmp.groupby(level='name').bfill().fillna(df.iloc[0]))
       .select_dtypes('number').div(2)
       .combine_first(tmp2).reset_index()[df.columns]
      )
ajsxfq5m

ajsxfq5m2#

如果name列中有相同的值,则可以使用DataFrame.reindex乘以range,并将前向和后向填充值除以s2中最后一个缺失的值,然后用s1的第一个值替换:

df1 = df.set_index('theta').reindex(range(0, 360, 30))

s1 = df1['r'].ffill()  
s2 = df1['r'].bfill().fillna(s1.iat[0])  

df = s1.add(s2).div(2).reset_index().assign(name = 'wind')[df.columns]
print (df)
    name  theta     r
0   wind      0  10.0
1   wind     30  17.0
2   wind     60  19.0
3   wind     90  14.0
4   wind    120  17.0
5   wind    150  17.5
6   wind    180  17.5
7   wind    210  18.0
8   wind    240  17.0
9   wind    270  11.0
10  wind    300  13.0
11  wind    330  11.5

使用DataFrame.interpolate和辅助行通过r的回填值进行插值的解决方案:

df1 = df.set_index('theta').reindex(range(0, 360, 30))

df = (pd.concat([df1, df1[['r']].bfill().iloc[[0]]])
        .interpolate().reset_index().iloc[:-1].assign(name='wind')[df.columns])

print (df)
    name  theta          r
0   wind      0  10.000000
1   wind     30  17.000000
2   wind     60  19.000000
3   wind     90  14.000000
4   wind    120  17.000000
5   wind    150  17.333333
6   wind    180  17.666667
7   wind    210  18.000000
8   wind    240  17.000000
9   wind    270  11.000000
10  wind    300  13.000000
11  wind    330  11.500000

如果可能,第一行缺失:

print (df)
   name  theta   r
2  wind     30  17
3  wind     60  19
4  wind     90  14
5  wind    120  17
6  wind    210  18
7  wind    240  17
8  wind    270  11
9  wind    300  13

df1 = df.set_index('theta').reindex(range(0, 360, 30))

df = (pd.concat([df1[['r']].ffill().iloc[[-1]], 
                 df1, 
                 df1[['r']].bfill().iloc[[0]]])
        .interpolate().reset_index().iloc[1:-1].assign(name='wind')[df.columns])

print (df)
    name  theta          r
1   wind      0  15.000000
2   wind     30  17.000000
3   wind     60  19.000000
4   wind     90  14.000000
5   wind    120  17.000000
6   wind    150  17.333333
7   wind    180  17.666667
8   wind    210  18.000000
9   wind    240  17.000000
10  wind    270  11.000000
11  wind    300  13.000000
12  wind    330  15.000000

相关问题