DataFrame:N个最大索引值(从level = 1)到n列

时间:2018-05-16 10:11:13

标签: python pandas dataframe group-by multi-index

我正在尝试转换这样的df:

df = pd.DataFrame({'A': ['A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2'],
      'B': ['B1', 'B1', 'B2', 'B2', 'B3', 'B3', 'B4', 'B5', 'B6', 'B7', 'B7', 'B8', 'B8']})

enter image description here

将n(此处为2)个最大指数(按B计数)取为:

enter image description here

我的做法:

df = df.groupby(['A', 'B'])['A'].count()
df = df.groupby(level=0).nlargest(2).reset_index(level=0, drop=True)
是什么让我(接近我需要的):

enter image description here

现在,我知道转换MultiIndex的唯一方法是:

df.reset_index(level=1)
df.unstack()

但他们不能给我我想要的东西。是否有任何数据框方法可以为我做,或者我需要使用apply来做。一种方法是循环遍历每一对:df.index.get_level_values(level=1)并将其放到2列的新df中。但这会破坏如果一个index.level = 0,将只有一个index.level = 1

另外:当计数相同时,我不在乎(nlargest)的顺序。

2 个答案:

答案 0 :(得分:1)

使用SeriesGroupBy.value_counts默认排序,按head选择前2个索引值,然后DataFrame构造函数:

a = df.groupby('A')['B'].apply(lambda x: x.value_counts().head(2).index.tolist())
print (a)
A
A1    [B1, B3]
A2    [B7, B8]
Name: B, dtype: object

如果想要使用您的代码:

df = df.groupby(['A', 'B'])['A'].count()
df = df.groupby(level=0).nlargest(2).reset_index(level=0, drop=True)

df = df.rename('C').reset_index().groupby('A')['B'].apply(list)
print (df)
A
A1    [B1, B2]
A2    [B7, B8]
Name: B, dtype: object
df1 = (pd.DataFrame(a.values.tolist(), index=a.index)
         .rename(columns=lambda x: x+1)
         .add_suffix('_nlargest'))
print (df1)
   1_nlargest 2_nlargest
A                       
A1         B1         B3
A2         B7         B8

答案 1 :(得分:1)

虽然@jezrael的回答更快更容易(我会用它),但这就是我开发的时候,我正在研究它:

df = pd.DataFrame({'A': ['A1', 'A1', 'A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2', 'A2'],
      'B': ['B1', 'B1', 'B2', 'B2', 'B3', 'B3', 'B4', 'B5', 'B6', 'B7', 'B7', 'B8', 'B8']})

df = df.groupby(['A', 'B'])['A'].count()
df = df.groupby(level=0).nlargest(2).reset_index(level=0, drop=True)
df = df.unstack()

df_new = pd.DataFrame(columns=['A', '1_Largest', '2_largest'])

for i, row in enumerate(['A1', 'A2']):
    df_new.loc[i, :] = row
    df_new.loc[i, '1_Largest'] = df.loc[row].sort_values(ascending=False).index[0]
    df_new.loc[i, '2_largest'] = df.loc[row].sort_values(ascending=False).index[1]

df_new.set_index('A')