【问题标题】:Pandas merge list with same id row wisePandas 合并具有相同 id 行的列表
【发布时间】:2020-12-23 13:24:41
【问题描述】:

如何在 pandas 中逐行连接列表类型的列?例如见下文-

之前,

1  a  [a,b,c]  
1  b  [a,d] 

之后,

1  b  [a,b,c,d]

我做了如下的逐列连接,

df['all_poi'] = df['poi_part1'] + df['poi_part2']

电流输出

location_id  city            all_poi
6265981     Port Severn     [Mount St. Louis Moonstone , Horseshoe Valley , Lake Muskoka]
6265981     Port Severn     [Mount St. Louis Moonstone ,  Little Lake Park , Bamboo Spa , Lake Huron]

预期输出

location_id    city             all_poi
6265981     Port Severn     [Mount St. Louis Moonstone , Horseshoe Valley , Lake Muskoka, Little Lake Park , Bamboo Spa , Lake Huron]

检查 all_poi 值它根据 location_id

合并值

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以在GroupBy.agg的自定义函数中创建集合:

    f = lambda x: list(set(z for y in x for z in y))
    df = df.groupby(['location_id', 'city'])['all_poi'].agg(f).reset_index()
    print (df)
      location_id    city                                            all_poi
    0        Port  Severn  [Bamboo Spa, Mount St.Louis Moonstone, Lake Hu...
    

    如果顺序和性能很重要,请使用 dict 删除重复项:

    f = lambda x: list(dict.fromkeys([z for y in x for z in y]).keys())
    

    另一个想法是使用unique:

    f = lambda x: pd.unique([z for y in x for z in y]).tolist()
    

    编辑:

    如果有多个列并且每个组需要第一个值:

    df.groupby('location_id').agg({'city': 'first', 'all_poi': f}).reset_index()
    

    如果需要其他聚合方法,例如summeanjoin

    df.groupby('location_id').agg({'city': 'first', 
                                   'all_poi': f, 
                                   'cols1':'sum', 
                                   'vals': ','.join, 
                                   'vals1': lambda x: list(x)}).reset_index()
    

    【讨论】:

    • 它有效,但我只想按位置 ID 分组并获取我的数据框的所有其他列
    • @AlwaysSunny - 您是否需要其他列的每个组的第一个值?
    • 这就是我最后的做法f = lambda x: list(set(z for y in x for z in y)) mapped_other = mapped_other.groupby(['location_id', 'city','state','country_code'])['all_poi'].agg(f).reset_index()
    • 先生好吗? @jezrael
    • 您一如既往地是我的明星和灵感。非常感谢先生 :) 继续为您提供出色的帮助
    【解决方案2】:

    看起来下面的答案更紧凑,但您可以将sum 与 groupby 一起应用以组合列表。然后创建一个集合去除重复,并从set 转换为list

    import pandas as pd
    
    df = pd.DataFrame([['1' ,'New York', ['a','b','c']], ['1', 'New York', ['a','d']]],
                       columns = ['location_id', 'city','all_poi'])
    
    df.groupby(('location_id'))['all_poi'].apply(sum).apply(set).apply(list)
    

    【讨论】:

    • 这就是我的回答伙伴☺️
    【解决方案3】:

    简单的sum()怎么样:

    res=df.groupby(["location_id"], as_index=False).agg({"city": "last", "all_poi": "sum"})
    res["all_poi"]=res["all_poi"].map(set)
    

    输出:

    Before
       location_id  ...                                                                all_poi
    0  6265981      ...  [Mount St. Louis Moonstone, Horseshoe Valley, Lake Muskoka]
    1  6265981      ...  [Mount St. Louis Moonstone, Little Lake Park, Bamboo Spa, Lake Huron]
    
    After:
       location_id  ...                                                                                                all_poi
    0  6265981      ...  {Horseshoe Valley, Lake Muskoka, Lake Huron, Bamboo Spa, Little Lake Park, Mount St. Louis Moonstone}
    

    【讨论】:

    • 不要使用 sum 来连接列表。它看起来很花哨,但它是二次的,应该被认为是不好的做法。 OP也需要删除重复项。
    • quadratic 是什么意思?我不确定我是否理解,为什么这是不好的做法,你肯定会这样做。 [1,2,3]+['a', 'b'] 连接列表,对吗?
    • 对于聚合用于扁平化列表,sum 是更差的性能方法(但看起来很酷;))
    • 谢谢,我会通读这些,没想到lambda 可以比简单的求和更快——但我可以看到这是一个更深层次的话题:)
    • 这取决于,如果列出则是,否则不是。
    猜你喜欢
    • 2021-11-02
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2021-12-13
    • 2022-11-20
    • 2020-01-02
    • 2014-07-22
    相关资源
    最近更新 更多