[英]Reshape a Pandas data frame with multi column key
我有一个熊猫数据框,其中有两列作为唯一值(eng_id,日期)。 我需要将其转换为以下形状,并通过equipment_id唯一值及其测量值创建列。 我怎样才能做到这一点?
From:
eng_id date equipment_id measurement
1 2016-01 100 20
1 2016-01 200 46
1 2016-01 300 18
1 2016-04 200 33
1 2016-05 200 27
2 2016-01 300 9
2 2016-01 400 15
2 2016-05 400 65
2 2016-05 500 51
2 2016-05 600 16
To:
ID 100 200 300 400 500 600
1,2016-01 20 46 18 0 0 0
1,2016-04 0 33 0 0 0 0
1,2016-05 0 27 0 0 0 0
2,2016-01 0 0 9 15 0 0
2,2016-05 0 0 0 65 51 16
Concanecate两列,将ID
和使用pivot
:
df['ID'] = df['eng_id'].astype(str) + ',' + df['date']
df = df.pivot(index='ID', columns='equipment_id', values='measurement').fillna(0).astype(int)
print (df)
equipment_id 100 200 300 400 500 600
ID
1,2016-01 20 46 18 0 0 0
1,2016-04 0 33 0 0 0 0
1,2016-05 0 27 0 0 0 0
2,2016-01 0 0 9 15 0 0
2,2016-05 0 0 0 65 51 16
df['ID'] = df['eng_id'].astype(str) + ',' + df['date']
df = df.set_index(['ID', 'equipment_id'])['measurement'].unstack(fill_value=0)
print (df)
equipment_id 100 200 300 400 500 600
ID
1,2016-01 20 46 18 0 0 0
1,2016-04 0 33 0 0 0 0
1,2016-05 0 27 0 0 0 0
2,2016-01 0 0 9 15 0 0
2,2016-05 0 0 0 65 51 16
但是如果需要ID
有2
列:
df = df.set_index(['eng_id', 'date', 'equipment_id'])['measurement'].unstack(fill_value=0)
print (df)
equipment_id 100 200 300 400 500 600
eng_id date
1 2016-01 20 46 18 0 0 0
2016-04 0 33 0 0 0 0
2016-05 0 27 0 0 0 0
2 2016-01 0 0 9 15 0 0
2016-05 0 0 0 65 51 16
对于列,添加reset_index
+ rename_axis
:
df = df.set_index(['eng_id', 'date', 'equipment_id'])['measurement'].unstack(fill_value=0)
.reset_index()
.rename_axis(None, axis=1)
print (df)
eng_id date 100 200 300 400 500 600
0 1 2016-01 20 46 18 0 0 0
1 1 2016-04 0 33 0 0 0 0
2 1 2016-05 0 27 0 0 0 0
3 2 2016-01 0 0 9 15 0 0
4 2 2016-05 0 0 0 65 51 16
但是如果得到:
ValueError:索引包含重复的条目,无法重塑
这意味着您有重复项,并且需要带有一些汇总函数(例如mean
, sum
...)的pivot_table
:
print (df)
eng_id date equipment_id measurement
0 1 2016-01 100 20 <-duplicate 1 2016-01 100
1 1 2016-01 100 30 <-duplicate 1 2016-01 100
2 1 2016-01 200 46
3 1 2016-01 300 18
4 1 2016-04 200 33
5 1 2016-05 200 27
6 2 2016-01 300 9
7 2 2016-01 400 15
8 2 2016-05 400 65
9 2 2016-05 500 51
10 2 2016-05 600 16
df['ID'] = df['eng_id'].astype(str) + ',' + df['date']
df = df.pivot_table(index='ID',
columns='equipment_id',
values='measurement',
fill_value=0,
aggfunc='mean')
print (df)
equipment_id 100 200 300 400 500 600
ID
1,2016-01 25 46 18 0 0 0 <= (20+30)/2=25
1,2016-04 0 33 0 0 0 0
1,2016-05 0 27 0 0 0 0
2,2016-01 0 0 9 15 0 0
2,2016-05 0 0 0 65 51 16
或者使用groupby
+ aggregate function
+ unstack
:
df['ID'] = df['eng_id'].astype(str) + ',' + df['date']
df = df.groupby(['ID', 'equipment_id'])['measurement'].mean().unstack(fill_value=0)
print (df)
equipment_id 100 200 300 400 500 600
ID
1,2016-01 25 46 18 0 0 0 <= (20+30)/2=25
1,2016-04 0 33 0 0 0 0
1,2016-05 0 27 0 0 0 0
2,2016-01 0 0 9 15 0 0
2,2016-05 0 0 0 65 51 16
@jezrael的答案涵盖了最惯用的方法。 对我而言,这只是一个探索性练习。 我想分享我的发现。 该技术假定['eng_id', 'date', 'equipment_id']
是唯一的。
z = list(zip(df.eng_id.values.tolist(), df.date.values.tolist()))
# i will be the positions I will use to insert into the values array
# u will be the tuples that make up the index
i, u = pd.Series(z).factorize()
idx = pd.MultiIndex.from_tuples(u, names=['eng_id', 'date'])
# j will bet be positions I will use to insert into the values array
# col will be the column labels
j, col = df.equipment_id.factorize()
# Create a place holder dataframe
d = pd.DataFrame(0, idx, col)
# fill the values
d.values[i, j] = df.measurement.values
print(d)
100 200 300 400 500 600
eng_id date
1 2016-01 20 46 18 0 0 0
2016-04 0 33 0 0 0 0
2016-05 0 27 0 0 0 0
2 2016-01 0 0 9 15 0 0
2016-05 0 0 0 65 51 16
定时
小数据
对于大数据,这看起来可能有所不同,但我尚未对其进行测试。
%%timeit
z = list(zip(df.eng_id.values.tolist(), df.date.values.tolist()))
i, u = pd.Series(z).factorize()
idx = pd.MultiIndex.from_tuples(u, names=['eng_id', 'date'])
j, col = df.equipment_id.factorize()
d = pd.DataFrame(0, idx, col)
d.values[i, j] = df.measurement.values
1000 loops, best of 3: 885 µs per loop
%timeit df.set_index(['eng_id', 'date', 'equipment_id'])['measurement'].unstack(fill_value=0)
100 loops, best of 3: 1.96 ms per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.