【问题标题】:Pandas - split columns and include countsPandas - 拆分列并包含计数
【发布时间】:2019-03-28 17:26:52
【问题描述】:

我有以下数据框:

            doc_id  is_fulltext
1243      dok:1            1
3310      dok:1            1
4370      dok:1            1
14403  dok:1020            1
17252  dok:1020            1
15977  dok:1020            0
16480  dok:1020            1
16252  dok:1020            1
468     dok:103            1
128    dok:1030            0
1673   dok:1038            1

我想将 is_fulltext 列拆分为两列,并同时计算文档的出现次数。

期望的输出:

 doc_id                 fulltext  non-fulltext
0           dok:1        3          0
1           dok:1020     4          1
2           dok:103      1          0
3           dok:1030     0          1
4           dok:1038     1          0


我按照Pandas - Create columns from column value, and fill with count的程序进行

该帖子显示了几种替代方法,建议使用分类或重新索引。我尝试了以下方法:

cats = ['fulltext', 'non_fulltext']
df_sorted['is_fulltext'] = pd.Categorical(df_sorted['is_fulltext'], categories=cats)
new_df = df_sorted.groupby(['doc_id', 'is_fulltext']).size().unstack(fill_value=0)

这里我得到一个 ValueError:

ValueError: Length of passed values is 17446, index implies 0

然后我尝试了这个方法


cats = ['fulltext', 'non_fulltext']
new_df = df_sorted.groupby(['doc_id','is_fulltext']).size().unstack(fill_value=0).reindex(columns=cats).reset_index()

虽然这在原始帖子中似乎运行良好,但我的计数中充满了 NAN(见下文)。我现在读到,在使用 reindex 和 categorical 时会发生这种情况,但我想知道为什么它似乎在原始帖子中有效。我该如何解决这个问题?任何人都可以帮忙吗?谢谢!

 doc_id                         fulltext  non-fulltext
0           dok:1                NaN          NaN
1           dok:1020             NaN          NaN
2           dok:103              NaN          NaN
3           dok:1030             NaN          NaN
4           dok:1038             NaN          NaN

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以GroupBydoc_id,将pd.value_counts 应用于每个组和unstack

    (df.groupby('doc_id').is_fulltext.apply(pd.value_counts)
                                     .unstack()
                                     .fillna(0)
                                     .rename(columns={0:'non-fulltext', 1:'fulltext'})
                                     .reset_index())
    
        doc_id      non-fulltext  fulltext
    0     dok:1           0.0       3.0
    1  dok:1020           1.0       4.0
    2   dok:103           0.0       1.0
    3  dok:1030           1.0       0.0
    4  dok:1038           0.0       1.0
    

    或者类似于您自己的方法,如果性能是一个问题,请改为:

    df.groupby(['doc_id','is_fulltext']).size()
                                        .unstack(fill_value=0)
                                        .rename(columns={0:'fulltext',1:'non_fulltext'})
                                        .reset_index()
    
    is_fulltext    doc_id  fulltext  non_fulltext
    0               dok:1         0             3
    1            dok:1020         1             4
    2             dok:103         0             1
    3            dok:1030         1             0
    4            dok:1038         0             1
    

    【讨论】:

    • 谢谢,这很好用。但是有一个小问题:它相当慢,特别是如果您有大量数据。有什么办法解决这个问题?
    • 稍后会调查一下@annika
    • @Annika 使用了您自己的答案。使用 reindex 将所有值设置为 nan。你想要一个重命名。这应该更快,因为 id 避免了任何 python 级别的循环
    • 非常感谢!令人惊讶的是一个小词有什么不同(重新索引与重命名)......
    【解决方案2】:

    我不知道这是否是最好的方法,但这应该适合你:

    import pandas as pd
    df = pd.DataFrame({"doc_id":["id1", "id2", "id1", "id2"], 
                       "is_fulltext":[1, 0, 1, 1]})
    df_grouped = df.groupby("doc_id").sum().reset_index()
    df_grouped["non_fulltext"] = df.groupby("doc_id").count().reset_index()["is_fulltext"] - df_grouped["is_fulltext"]
    df_grouped 
    

    输出是:

      doc_id  is_fulltext  non_fulltext
    0    id1            2             0
    1    id2            1             1
    

    【讨论】:

    • 谢谢,这很好用——除非你有大量的数据。它很快,但是,在最后几行中 non_fulltext 的值再次变为 NaN...
    猜你喜欢
    • 2021-10-04
    • 2019-07-25
    • 2020-12-10
    • 1970-01-01
    • 2020-08-02
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    相关资源
    最近更新 更多