【问题标题】:Reduce comma separated str in df if all strs identical如果所有 str 相同,则减少 df 中逗号分隔的 str
【发布时间】:2020-03-01 11:50:22
【问题描述】:

这是我目前的代码

import pandas as pd
from io import StringIO

data = StringIO("""
"name1","hej","7aa","a"
"name1","du","71al","a"
"name1","aj","74a","a"
"name1","oj","7aj","a"
"name2","fin","7ag","a"
"name2","katt","7a","a"
""")
df = pd.read_csv(data, header=0, names=["name","text2","text","as"])
df[['text2','text','as']] = df.groupby(['name']).transform(lambda 
x: ','.join(x))
df = df[['name','text','text2','as']].drop_duplicates()
df

让我走得更远。

df
    name          text     text2     as
0  name1  71al,74a,7aj  du,aj,oj  a,a,a
3  name2        7ag,7a  fin,katt    a,a

我只需要一行来检查每个列 ['text','text2','as'],如果所有逗号分隔的元素都相同,则只返回第一个

所以我想要的结果是

df
    name          text     text2     as
0  name1  71al,74a,7aj  du,aj,oj    a
3  name2        7ag,7a  fin,katt    a

我尝试过使用 split(',') 应用。无法让它工作。

我将这篇文章添加为第一个 cmets。我没有正确描述我的问题

如果我的 df 是这样的:

df
    name          text     text2     as
0  name1  71al,74a,7aj  du,aj,oj  a,b,a
3  name2        7ag,7a  fin,katt    a,a

我需要修改为:

df
    name          text     text2     as
0  name1  71al,74a,7aj  du,aj,oj  a,b,a
3  name2        7ag,7a  fin,katt    a

不是:

df
    name          text     text2     as
0  name1  71al,74a,7aj  du,aj,oj  a,b
3  name2        7ag,7a  fin,katt    a

谢谢

这是我的最终解决方案:

data = StringIO("""
"name1","hej","7aa","a"
"name1","du","71al","b"
"name1","aj","74a","a"
"name1","oj","7aj","a"
"name2","fin","7ag","a"
"name2","katt","7a","a"
""")
df = pd.read_csv(data, header=0, names=["name","text2","text","as"])
df[['text2','text','as']] = df.groupby(['name']).transform(lambda x: ','.join(x))
df = df[['name','text','text2','as']].drop_duplicates()
for col in df.columns:
    df[col] = df[col].str.split(',').map(lambda x: ','.join(set(x) if len(set(x)) == 1 else x))
df

我不得不求助于迭代。我无法使用 agg 获得预期的结果。此外,如果有人可以在这里向我解释 len(set(x)) == 1 的方式,那将不胜感激(由于逗号,它应该至少为 2 吗?)

【问题讨论】:

    标签: python-3.x pandas if-statement lambda apply


    【解决方案1】:

    试试

    df['as'] = df['as'].str.split(',').map(lambda x: ','.join(set(x) if len(set(x)) == 1 else x))
    

    【讨论】:

    • 如果像我的解决方案一样添加set,不需要再次拆分加入
    • 看起来不错。虽然我不明白!地图是如何工作的?
    • 对系列的每一行应用一个函数。 @LiamMcIntyre
    【解决方案2】:

    GroupBy.agg 与带有if-else 的自定义lambda 函数一起使用:

    df = (df.groupby('name')
            .agg(lambda x: ','.join(set(x) if len(set(x)) == 1 else x))
            .reset_index())
    print (df)
        name     text2          text     as
    0  name1  du,aj,oj  71al,74a,7aj  a,b,a
    1  name2  fin,katt        7ag,7a      a
    

    【讨论】:

    • 谢谢。那很好。不幸的是,如果所有元素都相同,我只能崩溃。如果只有一些相同,则使用集合会减少。
    • @LiamMcIntyre - 您可以更改数据样本以查看问题吗?
    • 完美,非常感谢。你看起来像个绝对的巫师。有没有学习资料?
    • @LiamMcIntyre - 这周我找到了不错的博客,希望对 link 有所帮助
    • @LiamMcIntyre - 我看到答案正在接受,也请参阅您的解决方案。你能解释更多I could not get the desired results with agg吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多