我有一个具有以下结构的数据框:
df= pd.DataFrame({"Origin": ['A','A','A','A','B','B','B'],"Name":["John","Bob","John","John","Bob","Elvis","John"],"Year":[2015,2015,2015,2015,2015,2016,2016]})
Origin |Name | Year
A John 2015
A Bob 2015
A John 2015
A John 2015
B Bob 2015
B Elvis 2016
B John 2016
我正在尝试按以下方式重新整理数据:每年,我要计算每个起源的每个名称的行数。在栏名和索引中的名称一起提出起源和年联合。 此处的预期输出应为:
index | A_2015 | A_2016 | B_2015 | B 2016 |
--------------------------------------------
John | 3 | 0 | 0 | 1
Bob | 1 | 0 | 1 | 0
Elvis | 0 | 0 | 0 | 1
原点可以分隔在不同的数据框中,这对我来说并不重要(我当前的代码正在将其分割)。
我的代码正在运行,但是如果发现它不雅,因为我将for循环和group_by结合在一起。这是我的镜头,我想知道是否有更好的方法来执行此转换。
dfTotalA = pd.DataFrame()
dfTotalB = pd.DataFrame()
for Year in TotalData.Year.unique():
df = TotalData.query("(Origin == 'A') & (YearHit == @Year)")[["Origin","Name"]].groupby('Name').Origin.size().to_frame(name='A_'+str(Year))
dfTotalA= pd.concat([dfTotal,df1],sort=False,axis=1)
df2 = TotalData.query("(Origin == 'B') & (YearHit == @Year)")[["Origin","Name"]].groupby('Name').Origin.size().to_frame(name='B_'+str(Year))
dfTotalB= pd.concat([dftotalB,df2],sort=False,axis=1)
Completedf = pd.concat(dfTotalA,dftotalB],sort=False,axis=1)
Completedf.fillna(0,inplace=True)
答案 0 :(得分:1)
一种方法:
new_df = (df.groupby(['Origin', 'Year'])
.Name
.value_counts()
.unstack(['Origin'], fill_value=0)
.unstack('Year', fill_value=0)
)
给出:
Origin A B
Year 2015 2016 2015 2016
Name
Bob 1 0 1 0
Elvis 0 0 0 1
John 3 0 0 1
然后您可以使用以下方式重命名列:
new_df.columns = [f'{a}_{b}' for a,b in new_df.columns]
答案 1 :(得分:1)
我们可以使用count
创建一个GroupBy.transform
列。然后pivot_table
。最后展平我们的MultiIndex
列:
df['cnt'] = df.groupby(['Origin', 'Name'])['Year'].transform('count')
piv = df.pivot_table(index='Name', columns=['Origin', 'Year'], fill_value=0)
piv.columns = [f'{c[1]}_{c[2]}'for c in piv.columns]
输出
A_2015 B_2015 B_2016
Name
Bob 1 1 0
Elvis 0 0 1
John 3 0 1