我有一个数据框。每个ID都有几个代码,每个代码都有统计信息。并非所有ID都具有其他人拥有的所有代码。 我需要旋转数据框,以便每个ID都有一行,每对代码状态对都有一列。
如何使用pandas 0.24.2和python 3.6最有效地做到这一点?
谢谢
import pandas as pd
df = pd.DataFrame({'id':[11, 11, 11, 12, 12, 13], 'code':['a', 'b', 'c', 'a', 'b', 'a'], 'max':[111, 112, 113, 221, 222, 333], 'min':[10, 11, 12, 21, 22, 33]})
df
Results in
id code max min
0 11 a 111 11
1 11 b 112 12
2 11 c 113 13
3 12 a 221 21
4 12 b 222 22
5 13 c 333 33
我需要将其转换为
id a_max a_min b_max b_min c_max c_min
11 111 11 112 12 113 13
12 221 21 222 22 None None
13 None None None None 333 33
更新 我发布的代码有误。 对于代码“ a”,代码应为11、12、13,而不是10、11、12。
import pandas as pd
df = pd.DataFrame({'id':[11, 11, 11, 12, 12, 13], 'code':['a', 'b', 'c', 'a', 'b', 'a'], 'max':[111, 112, 113, 221, 222, 333], 'min':[11, 12, 13, 21, 22, 33]})
df
答案 0 :(得分:1)
将DataFrame.set_index
与DataFrame.unstack
和DataFrame.sort_index
一起使用,然后展平MultiIndex
并按reset_index
将索引转换为列:
df1 = df.set_index(['id','code']).unstack().sort_index(axis=1, level=1)
df1.columns = df1.columns.map('_'.join)
df1 = df1.reset_index()
print (df1)
id max_a min_a max_b min_b max_c min_c
0 11 111.0 10.0 112.0 11.0 113.0 12.0
1 12 221.0 21.0 222.0 22.0 NaN NaN
2 13 333.0 33.0 NaN NaN NaN NaN
如果可能的话,有必要成对重复,请按DataFrame.pivot_table
进行汇总:
df = pd.DataFrame({'id':[11, 11, 11, 12, 12, 13],
'code':['a', 'a', 'c', 'a', 'b', 'a'],
'max':[111, 112, 113, 221, 222, 333],
'min':[10, 11, 12, 21, 22, 33]})
print (df)
id code max min
0 11 a 111 10 <--- 11, a
1 11 a 112 11 <--- 11, a
2 11 c 113 12
3 12 a 221 21
4 12 b 222 22
5 13 a 333 33
df1 = df.pivot_table(index='id',columns='code', aggfunc='mean').sort_index(axis=1, level=1)
#alternative
#df1 = df.groupby(['id','code']).mean().unstack().sort_index(axis=1, level=1)
df1.columns = df1.columns.map('_'.join)
df1 = df1.reset_index()
print (df1)
id max_a min_a max_b min_b max_c min_c
0 11 111.5 10.5 NaN NaN 113.0 12.0
1 12 221.0 21.0 222.0 22.0 NaN NaN
2 13 333.0 33.0 NaN NaN NaN NaN
答案 1 :(得分:0)
如果您只有2列(最小值和最大值),则可以执行2步操作来解决该问题。
# convert the data from long to wide format for max and min
df_max = df.pivot(index="id", columns="code", values="max").reset_index()
df_min = df.pivot(index="id", columns="code", values="min").reset_index()
# join the max and min dataframe with a suffix
merged_df = pd.merge(df_max, df_min, on="id", how="outer", suffixes=("_max", "_min"))
输出:
code id a_max b_max c_max a_min b_min c_min
0 11 111.0 112.0 113.0 11.0 12.0 13.0
1 12 221.0 222.0 NaN 21.0 22.0 NaN
2 13 333.0 NaN NaN 33.0 NaN NaN