我有一个包含几个分类变量的Pandas DataFrame。例如:
import pandas as pd
d = {'grade':['A','B','C','A','B'],
'year':['2013','2013','2013','2012','2012']}
df = pd.DataFrame(d)
我想将其转换为具有以下属性的MultiIndex DataFrame:
例如:
有人可以建议一种创建这个MultiIndex DataFrame的方法吗?
另一种方法可以使用melt
和groupby
:
df_out = df.melt().groupby(['variable','value']).size().to_frame(name='n')
df_out['proportion'] = df_out['n'].div(df_out.n.sum(level=0),level=0)
print(df_out)
输出:
n proportion
variable value
grade A 2 0.4
B 2 0.4
C 1 0.2
year 2012 2 0.4
2013 3 0.6
并且,如果你真的想变得疯狂并且在单行中做:
(df.melt().groupby(['variable','value']).size().to_frame(name='n')
.pipe(lambda x: x.assign(proportion = x[['n']]/x.groupby(level=0).transform('sum'))))
使用@Wen pct计算升级的解决方案:
(df.melt().groupby(['variable','value']).size().to_frame(name='n')
.pipe(lambda x: x.assign(proportion = x['n'].div(x.n.sum(level=0),level=0))))
你可以尝试这个..
df1=df.apply(pd.value_counts).stack().swaplevel(0,1).to_frame('n')
df1['pct']=df1['n'].div(df1.n.sum(level=0),level=0)
df1
Out[89]:
n pct
year 2012 2.0 0.4
2013 3.0 0.6
grade A 2.0 0.4
B 2.0 0.4
C 1.0 0.2
Stey by step方法:
df1 = df.groupby("grade").count()
df2 = df.groupby("year").count()
df1.columns = ['n']
df2.columns = ['n']
df1['proportion'] = df1.divide(df1.sum())
df2['proportion'] = df2.divide(df2.sum())
df_new = pd.concat([df1, df2], keys=['grade', 'year'], names=['variable'])
concat
时,可以指定keys
作为最外层索引。同时使用names=
为此新索引指定名称。可以通过在循环中堆叠每个变量来创建DataFrame,但这似乎效率低下。例如。:
d_end = []
for c in df.columns:
temp_df = pd.DataFrame(df[c].value_counts().rename('n'))
temp_df['proportion'] = temp_df['n'] / temp_df['n'].sum()
temp_df['variable'] = c
temp_df.set_index(['variable',temp_df.index],inplace=True)
d_end.append(temp_df)
df_end = pd.concat(d_end,axis=0)
我希望有人可以建议一个更好的方法,避免循环。