假设我有一个简单的Pandas DataFrame,其中一列包含国家/地区名称,另一列包含一些值。例如:
# Import Python Libraries
import numpy as np
import pandas as pd
# Create Sample DataFrame
df = pd.DataFrame(data={'Country': ['United States','United States','United States','United States', \
'United States','United States','United States','United States', \
'United States','United States','United States','United States', \
'Canada','Canada','Canada','Canada','Canada','Canada','Mexico', \
'Mexico','Mexico','Mexico','England','England','England','England', \
'England','England','England','England','England','England','England', \
'England','England','England','France','France','France','Spain','Germany', \
'Germany','Germany','Germany','Germany','Germany','Germany','Germany', \
'Germany','Germany'], 'Value': np.random.randint(1000, size=50)})
哪个生成:
print(df.head())
Index Country Value
0 United States 943
1 United States 567
2 United States 534
3 United States 700
4 United States 470
我的问题是,在Python中将此DataFrame转换成每个国家/地区都有自己的列,并且该国家/地区的所有值都列在该列中的最简单方法是什么?换句话说,如何轻松创建一个DataFrame,其中列数是“ Country”列中国家/地区的唯一计数,并且每列的长度将根据相应国家/地区在原始DataFrame中出现的次数而变化?
以下是提供解决方案的示例代码:
# Store Unique Country Names in Variable
columns = df['Country'].unique()
# Create Individual Country DataFrames
df_0 = df[df['Country'] == columns[0]]['Value'].values.tolist()
df_1 = df[df['Country'] == columns[1]]['Value'].values.tolist()
df_2 = df[df['Country'] == columns[2]]['Value'].values.tolist()
df_3 = df[df['Country'] == columns[3]]['Value'].values.tolist()
df_4 = df[df['Country'] == columns[4]]['Value'].values.tolist()
df_5 = df[df['Country'] == columns[5]]['Value'].values.tolist()
df_6 = df[df['Country'] == columns[6]]['Value'].values.tolist()
# Create Desired Output DataFrame
data_dict = {columns[0]: df_0, columns[1]: df_1, columns[2]: df_2, columns[3]: df_3, columns[4]: df_4, columns[5]: df_5, columns[6]: df_6}
new_df = pd.DataFrame({k:pd.Series(v[:len(df)]) for k,v in data_dict.items()})
哪个生成:
print(new_df)
United States Canada Mexico England France Spain Germany
0 838.0 135.0 496.0 568.0 71.0 588.0 811.0
1 57.0 118.0 268.0 716.0 422.0 NaN 107.0
2 953.0 396.0 850.0 860.0 707.0 NaN 318.0
3 251.0 294.0 815.0 888.0 NaN NaN 633.0
4 127.0 466.0 NaN 869.0 NaN NaN 910.0
5 892.0 824.0 NaN 776.0 NaN NaN 472.0
6 11.0 NaN NaN 508.0 NaN NaN 466.0
7 563.0 NaN NaN 299.0 NaN NaN 200.0
8 864.0 NaN NaN 568.0 NaN NaN 637.0
9 810.0 NaN NaN 78.0 NaN NaN 392.0
10 268.0 NaN NaN 106.0 NaN NaN NaN
11 389.0 NaN NaN 153.0 NaN NaN NaN
12 NaN NaN NaN 217.0 NaN NaN NaN
13 NaN NaN NaN 941.0 NaN NaN NaN
虽然上面的代码有效,但是对于较大的数据集,这显然不是一个可行的解决方案。从原始DataFrame生成此结果的最有效方法是什么?
谢谢!
答案 0 :(得分:2)
可能不是最高效的解决方案,但是它将使所有事情都变得合理。
df1 = df.groupby('Country').Value.agg(list).apply(pd.Series).T
df1.columns.name=None
输出:df1
Canada England France Germany Mexico Spain United States
0 653.0 187.0 396.0 491.0 251.0 433.0 919.0
1 215.0 301.0 25.0 107.0 755.0 NaN 435.0
2 709.0 581.0 858.0 691.0 158.0 NaN 166.0
3 626.0 706.0 NaN 572.0 767.0 NaN 352.0
4 516.0 999.0 NaN 393.0 NaN NaN 906.0
5 847.0 688.0 NaN 780.0 NaN NaN 489.0
6 NaN 722.0 NaN 19.0 NaN NaN 322.0
7 NaN 728.0 NaN 166.0 NaN NaN 753.0
8 NaN 765.0 NaN 299.0 NaN NaN 155.0
9 NaN 956.0 NaN 449.0 NaN NaN 438.0
10 NaN 41.0 NaN NaN NaN NaN 588.0
11 NaN 43.0 NaN NaN NaN NaN 796.0
12 NaN 485.0 NaN NaN NaN NaN NaN
13 NaN 218.0 NaN NaN NaN NaN NaN
另一种选择是利用Coldspeed's justify function和Yuca的数据透视输出:
import numpy as np
df2 = df.pivot(index=None, columns='Country', values='Value')
df2 = pd.DataFrame(
justify(df2.values, invalid_val=np.NaN, axis=0, side='up'),
columns=df2.columns
).dropna(0, 'all')
df2.columns.name=None
输出:df2
Canada England France Germany Mexico Spain United States
0 653 187 396 491 251 433 919
1 215 301 25 107 755 NaN 435
2 709 581 858 691 158 NaN 166
3 626 706 NaN 572 767 NaN 352
4 516 999 NaN 393 NaN NaN 906
5 847 688 NaN 780 NaN NaN 489
6 NaN 722 NaN 19 NaN NaN 322
7 NaN 728 NaN 166 NaN NaN 753
8 NaN 765 NaN 299 NaN NaN 155
9 NaN 956 NaN 449 NaN NaN 438
10 NaN 41 NaN NaN NaN NaN 588
11 NaN 43 NaN NaN NaN NaN 796
12 NaN 485 NaN NaN NaN NaN NaN
13 NaN 218 NaN NaN NaN NaN NaN
答案 1 :(得分:2)
将groupby
,cumcount
和unstack
与T
一起使用:
df.set_index(['Country',df.groupby('Country').cumcount()])['Value'].unstack().T
输出:
Country Canada England France Germany Mexico Spain United States
0 535.0 666.0 545.0 522.0 581.0 525.0 394.0
1 917.0 130.0 76.0 882.0 563.0 NaN 936.0
2 344.0 376.0 960.0 442.0 247.0 NaN 819.0
3 760.0 272.0 NaN 604.0 976.0 NaN 975.0
4 745.0 199.0 NaN 512.0 NaN NaN 123.0
5 654.0 102.0 NaN 114.0 NaN NaN 690.0
6 NaN 570.0 NaN 318.0 NaN NaN 568.0
7 NaN 807.0 NaN 523.0 NaN NaN 385.0
8 NaN 18.0 NaN 890.0 NaN NaN 451.0
9 NaN 26.0 NaN 635.0 NaN NaN 282.0
10 NaN 871.0 NaN NaN NaN NaN 771.0
11 NaN 122.0 NaN NaN NaN NaN 505.0
12 NaN 0.0 NaN NaN NaN NaN NaN
13 NaN 578.0 NaN NaN NaN NaN NaN
答案 2 :(得分:0)
pd.pivot
带您到中间,这里的问题是您的索引没有信息,因此您的非NaN值不在df的顶部
df.pivot(index=None, columns='Country', values = 'Value')
Country Canada England France ... Mexico Spain United States
0 NaN NaN NaN ... NaN NaN 992.0
1 NaN NaN NaN ... NaN NaN 814.0
2 NaN NaN NaN ... NaN NaN 489.0
3 NaN NaN NaN ... NaN NaN 943.0
4 NaN NaN NaN ... NaN NaN 574.0
5 NaN NaN NaN ... NaN NaN 428.0
6 NaN NaN NaN ... NaN NaN 907.0
7 NaN NaN NaN ... NaN NaN 899.0
8 NaN NaN NaN ... NaN NaN 379.0
9 NaN NaN NaN ... NaN NaN 130.0