【问题标题】:Adding rows to a Pandas dataframe based on a list in a column (and vice versa)根据列中的列表向 Pandas 数据框添加行(反之亦然)
【发布时间】:2017-05-17 05:54:53
【问题描述】:

我有这个数据框:

dfx = pd.DataFrame([[1,2],['A','B'],[['C','D'],'E']],columns=list('AB'))
        A  B
0       1  2
1       A  B
2  [C, D]  E

...我想在...中转换的...

        A  B
0       1  2
1       A  B
2       C  E
3       D  E

...如果是列表,则为 A 列中包含的每个值添加一行。

哪种方式最pythonic?

反之亦然,如果我想按列(比如说 B)分组并在 A 列中有分组值的列表? (所以和上面的例子相反)

提前致谢,

詹卢卡

【问题讨论】:

    标签: python list pandas dataframe group-by


    【解决方案1】:

    您有混合数据框 - intstrlist 值(非常有问题,因为许多函数会引发错误),所以首先将所有数字转换为 str where 和掩码是 to_numeric使用参数errors='coerce' 将非数字转换为NaN

    dfx.A = dfx.A.where(pd.to_numeric(dfx.A, errors='coerce').isnull(), dfx.A.astype(str))
    print (dfx)
            A  B
    0       1  2
    1       A  B
    2  [C, D]  E
    

    然后通过np.repeat 创建新的DataFrame 并通过chain.from_iterable 创建lists 的平面值:

    df = pd.DataFrame({
            "B": np.repeat(dfx.B.values, dfx.A.str.len()),
            "A": list(chain.from_iterable(dfx.A))})
    print (df)
       A  B
    0  1  2
    1  A  B
    2  C  E
    3  D  E
    

    Pure pandas 解决方案将列A 转换为list,然后创建新的DataFrame.from_records。然后drop原创专栏Ajoinstackeddf

    df = pd.DataFrame.from_records(dfx.A.values.tolist(), index = dfx.index)
    df = dfx.drop('A', axis=1).join(df.stack().rename('A')
            .reset_index(level=1, drop=True))[['A','B']]
    print (df)
       A  B
    0  1  2
    1  A  B
    2  C  E
    2  D  E
    

    如果需要lists,请使用groupbyapply tolist

    print (df.groupby('B')['A'].apply(lambda x: x.tolist()).reset_index())
       B       A
    0  2     [1]
    1  B     [A]
    2  E  [C, D]
    

    但如果需要list,仅当length 的值更多,因为1 是必要的if..else

    print (df.groupby('B')['A'].apply(lambda x: x.tolist() if len(x) > 1 else x.values[0])
             .reset_index())
       B       A
    0  2       1
    1  B       A
    2  E  [C, D]
    

    【讨论】:

    • 太棒了!谢谢
    • 不幸的是,如果我在 A 列中有多个字符的字符串 es ['HOME','B','C],则该解决方案不起作用,因为它将结果拆分为 [H, O,M,E,B,C]。任何想法?谢谢
    • 我测试了第一个 numpy 解决方案,效果很好,在第二个解决方案中需要将 df = pd.DataFrame.from_records(dfx.A.values.tolist(), index = dfx.index) 更改为 df = pd.DataFrame.from_records(dfx.A.values.tolist())
    • 我用dfx = pd.DataFrame([[1,2],['A','B'],[['HOME','C','D'],'E']],columns=list('AB'))测试它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多