将系列索引(在模式上匹配)转换为数据帧列



>我有一个系列(索引如图所示)显示为

E1         543
Units1_E   100
E2         553
Units2_E   420
E3         513
Units3_E   110
F1         243
Units1_F   500
F2         450
Units2_F   300
F3         400
Units3_F   200

我希望将其转换为数据帧,以便输出为

E_F     Units
543     100
553     420
513     110
243     500
450     300
400     200

所以所需的输出更像是一个对值列。 不确定如何有效地完成此操作,正在考虑使用正则表达式来过滤系列索引?

如果需要,可以匹配系列中的配对和取消配对值,通过整数除法创建MultiIndex,用长度为Series的数组取模,并通过Series.unstack重塑:

arr = np.arange(len(s))
s.index = [arr// 2, arr % 2]
df = s.unstack()
df.columns = ['E_F','Units']
print (df)
E_F  Units
0  543    100
1  553    420
2  513    110
3  243    500
4  450    300
5  400    200

或者通过索引创建新的数据帧 - 配对和取消配对值:

#pandas 0.24+
a = s.to_numpy()
#pandas below
#a = s.values
df = pd.DataFrame({'E_F':a[::2], 'Units':a[1::2]})
print (df)
E_F  Units
0  543    100
1  553    420
2  513    110
3  243    500
4  450    300
5  400    200

另一个想法(像前 2 个一样慢)是测试索引的第一个值是否EF,创建Series并通过GroupBy.cumcountMultiIndex

idx = pd.Series(np.where(s.index.str[0].isin(['E','F']), 'E_F','Units'))
s.index = [idx.groupby(idx).cumcount(), idx]
df = s.unstack()
print (df)
E_F  Units
0  543    100
1  553    420
2  513    110
3  243    500
4  450    300
5  400    200

使用以下代码:

>>> df = pd.DataFrame({i: pd.Series(x.values.ravel()) 
for i, x in pd.DataFrame(s).T.groupby(lambda x: x[0] in ['E', 'F'], axis=1)})
>>> df.columns = ['E_F', 'Units']
>>> df
E_F  Units
0  100    543
1  420    553
2  110    513
3  500    243
4  300    450
5  200    400
>>> 

我在s上使用zip来构建数据帧,s.shiftreindex只选择奇数行:

pd.DataFrame(list(zip(s.shift(), s)), columns=['E_F', 'Units']).reindex(index=range(1,s.size,2))
Out[225]:
E_F  Units
1   543.0    100
3   553.0    420
5   513.0    110
7   243.0    500
9   450.0    300
11  400.0    200

最新更新