Python Pandas为groupby中的每列获取三个最常见的值

Python Pandas为groupby中的每列获取三个最常见的值,python,pandas,Python,Pandas,我有一张这样的桌子: colour number letter 0 red one a 1 red two b 2 red two c 3 blue two a 4 blue two b 5 green one a 6 green two b 7 green three c 这是我做的: df = pd.DataFrame([ ('red', 'one', 'a'), ('red', 'two',

我有一张这样的桌子:

  colour number letter
0 red    one    a
1 red    two    b
2 red    two    c
3 blue   two    a
4 blue   two    b
5 green  one    a
6 green  two    b
7 green  three  c
这是我做的:

df = pd.DataFrame([
    ('red', 'one', 'a'),
    ('red', 'two', 'b'),
    ('red', 'two', 'c'),
    ('blue', 'two', 'a'),
    ('blue', 'two', 'b'),
    ('green', 'one', 'a'),
    ('green', 'two', 'b'),
    ('green', 'three', 'c')
], columns=['colour', 'number', 'letter'])
我想按颜色对表格进行分组,然后为每个剩余的列获取三个最常见的值。如果一个列没有三个唯一的值,那么最后一个值可以重复,也可以是
NaN
,两者都可以。输出如下所示:

       colour  red  blue  green  
number 1       two  two   one
       2       one  two   two
       3       one  two   three
letter 1       a    a     a
       2       b    b     b
       3       c    b     c
或:

我已经为一个专栏做了这项工作:

df.groupby('colour').number
  .value_counts()
  .groupby(level=0)
  .head(3)
输出:

colour  number  
blue    two     2
green   one     1
        two     1
        three   1
red     two     2
        one     1
但是,我希望对数据帧中的所有列执行此操作,并获得如示例所示的输出。我完全卡住了

k=df.groupby(['colour','letter']).number.value_counts(lambda x : x).groupby(level=0).head(3)

尝试:

印刷品:

蓝色、绿色、红色
一二三二
二二二一
三二一
信1 b
2 a a a
3 a c c

不漂亮,但我完成了:

def分析_col(df、col、grpby):
top3:pd.Series=df.groupby(grpby)[col].value_counts().groupby(level=0).head(3)
gg=pd.DataFrame({
g[0]:g[1]。索引。获取_级别_值(1)。到_系列(索引=范围(1,len(g[1])+1))。重新索引(范围(1,4))
对于top3.groupby中的g(级别=0)
})
返回pd.concat({col:gg},names=[grpby])
def分析_df(df,grpby):
返回pd.concat([analyze_col(df,col,grpby)for col in df.columns如果col!=grpby])
打印(分析df(df,“颜色”))
蓝绿红
颜色
一二一二
2南三一
3楠2楠
信1 a
2b
3 NaN c c

谢谢您的建议,但这与我在问题中提出的问题不符。我需要它给我的前3个值,每列按颜色分组。在这里,您已按颜色分组,然后按字母分组,并仅给出数字的前3个值。因此,在我的示例输出中,您将看到对于
red
而言,
number
最常见的值是
two
,但您给出了完全不同的值
k=df.groupby(['colour','letter']).number.value_counts(lambda x : x).groupby(level=0).head(3)

Output
colour  letter  number
blue    a       two       1.0
        b       two       1.0
green   a       one       1.0
        b       two       1.0
        c       three     1.0
red     a       one       1.0
        b       two       1.0
        c       two       1.0
Name: number, dtype: float64
def fn(x):
    return pd.Series(
        (x.value_counts().index[:3].tolist() + [np.nan, np.nan])[:3],
        index=range(1, 4),
    )


out = pd.concat(
    [
        df.groupby("colour")[col].apply(fn).unstack(level=0).ffill()
        for col in df.loc[:, "number":]
    ],
    keys=df.loc[:, "number":],
)
print(out)