代码之家  ›  专栏  ›  技术社区  ›  LoicM

将apply的输出作为dict保留在分类数据帧中

  •  1
  • LoicM  · 技术社区  · 5 年前

    让我们从一个简单的 pandas.DataFrame

    import pandas as pd
    
    df = pd.DataFrame({"a": [1, 2, 3], "b": [2, 4, 4]})    
    print(df)
    >>>    a  b
        0  1  2
        1  2  4
        2  3  4
    

    我想知道在我的数据帧的每一列中有什么不同的值,有多少次出现,每一列在一个漂亮的字典中表示(我知道以这种方式转换为字典可能不是最佳实践,但我需要它来做我的说明)

    df.apply(lambda x: x.value_counts().to_dict())
    >>> a    {3: 1, 2: 1, 1: 1}
        b          {4: 2, 2: 1}
    dtype: object
    

    到目前为止还不错吧?如果我的数据帧是另一种类型,比如说类别,会发生什么?我也期待同样的结果,对吧?

    绝对不是:

    df = df.astype('category') # Let's keep the same values, but now as type categorical
    df.apply(lambda x: x.value_counts().to_dict())
    >>>      a    b
         1  1.0  NaN
         2  1.0  1.0
         3  1.0  NaN
         4  NaN  2.0
    

    我一开始有点奇怪 pd.Series ,然后是 pd.DataFrame 你知道为什么会有这种行为吗?更重要的是,如何防止这种情况发生?

    编辑:只要原始数据帧的一列是分类列,这似乎就可以工作。 df['a'] = df['a'].astype('category'] 产生与我的第二个例子相同的结果

    result_type ,无济于事

    1 回复  |  直到 5 年前
        1
  •  0
  •   LoicM    5 年前

    当然,我在输入完问题之后就找到了一个快速解决方法:在进行计数之前,只需将数据帧中的每一列转换为“object”

    df = df.astype('object') # the df is originally categorical here
    df.apply(lambda x: x.value_counts().to_dict())
    

    我会保持我的问题开放的情况下,有人发现一个不那么黑客的答案,当然可以解释为什么这种行为!

        2
  •  0
  •   Quang Hoang    5 年前

    我不知道为什么会这样。但解决这个问题的方法是做一个列表:

    df = df.astype('category')
    pd.Series({c:df[c].value_counts().to_dict() for c in df.columns})
    

    输出:

    a    {3: 1, 2: 1, 1: 1}
    b          {4: 2, 2: 1}
    dtype: object
    
        3
  •  0
  •   Georgina Skibinski    5 年前

    df.stack().groupby(level=1).value_counts().groupby(level=0).agg(lambda x: dict(zip(x.index.get_level_values(1), x)))
    

    输出(与是否 category

    a    {1: 1, 2: 1, 3: 1}
    b          {4: 2, 2: 1}
    dtype: object