>我有一个系列(索引如图所示)显示为
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 个一样慢)是测试索引的第一个值是否E
或F
,创建Series
并通过GroupBy.cumcount
MultiIndex
:
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.shift
reindex
只选择奇数行:
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