Pandas groupby with value_counts并在新数据帧中生成列

Jak*_*ris 0 python dataframe pandas

给定一个数据框,其中包含特定事件的"名称",发生的年份及其类型,如下所示:

index  name  year  type  extracolumns
  0    'a'   2014  'X'     stuff
  1    'a'   2014  'X'     stuff
  2    'a'   2014  'Y'     stuff
  3    'a'   2014  'Y'     stuff
  4    'a'   2015  'X'     stuff
  5    'a'   2015  'X'     stuff
  6    'a'   2015  'Y'     stuff
  7    'b'   2014  'X'     stuff
  8    'b'   2015  'Y'     stuff
  9    'c'   2014  'Z'     stuff
Run Code Online (Sandbox Code Playgroud)

我想要一个由事件的'name'索引的数据帧,它按年份计算每个'type'的数量.理想情况下它看起来像:

index  type_X_2014  type_Y_2014  type_Z_2014  type_X_2015  type_Y_2015  type_Z_2015
 'a'        2            2            0             2           1           0
 'b'        1            0            0             0           1           0
 'c'        0            0            1             0           0           0
Run Code Online (Sandbox Code Playgroud)

这应该有nunique(types)*nunique(years)列.显然这将涉及groupby和一些value_counts.有没有办法动态完成这个,而无需对列名进行硬编码?非常感谢.

unu*_*tbu 5

您可以使用pd.crosstab创建频率表:

import sys
import pandas as pd
pd.options.display.width = sys.maxsize
df = pd.DataFrame({'extracolumns': ['stuff', 'stuff', 'stuff', 'stuff', 'stuff', 'stuff', 'stuff', 'stuff', 'stuff', 'stuff'], 'index': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'name': ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'c'], 'type': ['X', 'X', 'Y', 'Y', 'X', 'X', 'Y', 'X', 'Y', 'Z'], 'year': [2014, 2014, 2014, 2014, 2015, 2015, 2015, 2014, 2015, 2014]}) 

result = pd.crosstab(df['name'], [df['year'], df['type']], dropna=False)
result.columns = ['type_{}_{}'.format(typ,year) for year,typ in result.columns]

print(result)
Run Code Online (Sandbox Code Playgroud)

产量

      type_X_2014  type_Y_2014  type_Z_2014  type_X_2015  type_Y_2015  type_Z_2015
name                                                                              
a               2            2            0            2            1            0
b               1            0            0            0            1            0
c               0            0            1            0            0            0
Run Code Online (Sandbox Code Playgroud)

如果您不想对列名进行硬编码,但是您知道列的位置(序数索引),则可以使用iloc按位置引用列:

result = pd.crosstab(df.iloc[:,1], [df.iloc[:, 2], df.iloc[:, 3]])
Run Code Online (Sandbox Code Playgroud)

即使所有频率都为零,保持列的dropna=False原因crosstab.这确保了nunique(types)*nunique(years)列 - 包括type_Z_2015.