Pandas中groupby的按行合并

7

我有一个类似于下面这样的大型数据框(可以使用df=pd.read_clipboard(sep='\s\s+')进行复制粘贴):

    user_nm    month    unique_ips  shifted_ips     halves  quarters    mo_pairs
    100118231   2   set([142.136])  set([])         h1  q1  p1
    100118231   3   set([142.136])  set([142.136])  h1  q1  p2
    100118231   6   set([108.0])    set([142.136])  h1  q2  p3
    100118231   7   set([108.0])    set([108.0])    h2  q3  p4
    100118231   8   set([142.136])  set([108.0])    h2  q3  p4
    100118231   9   set([142.136])  set([142.136])  h2  q3  p5
    100118231   10  set([142.136])  set([142.136])  h2  q4  p5
    100118231   11  set([142.136])  set([142.136])  h2  q4  p6
    100406016   3   set([50.192])   set([])         h1  q1  p2
    100406016   7   set([50.192])   set([50.192])   h2  q3  p4

对于每个用户,我想按照“halves”(或“quarters”,或“mo_pairs”)分组,并获取“unique_ips”和“shifted_ips”的并集。
我可以像下面这样对字段进行分组:
In [265]: a=df.groupby(['user_nm','halves'])

In [266]: a.head()
Out[266]: 

            user_nm month   unique_ips  shifted_ips halves  quarters    mo_pairs
user_nm halves                              
100118231   h1  0   100118231   2   set([142.136])  set([]) h1  q1  p1
        1   100118231   3   set([142.136])  set([142.136])  h1  q1  p2
        2   100118231   6   set([108.0])    set([142.136])  h1  q2  p3
    h2  3   100118231   7   set([108.0])    set([108.0])    h2  q3  p4
        4   100118231   8   set([142.136])  set([108.0])    h2  q3  p4
        5   100118231   9   set([142.136])  set([142.136])  h2  q3  p5
        6   100118231   10  set([142.136])  set([142.136])  h2  q4  p5
        7   100118231   11  set([142.136])  set([142.136])  h2  q4  p6
100406016   h1  8   100406016   3   set([50.192])   set([]) h1  q1  p2
    h2  9   100406016   7   set([50.192])   set([50.192])   h2  q3  p4

然而,当我尝试合并这些行时,出现错误:

In [267]: a.apply(lambda x: x[2] & x[3], axis=1)
TypeError: <lambda>() got an unexpected keyword argument 'axis'

理想情况下,我希望像这样:

的东西。

                  unique_ips    shifted_ips
user_nm   halves        
100118231   h1  set([142.136, 108.0])   set([142.136])
100118231   h2  set([142.136,108.0])    set([142.136,108.0])
100406016   h1  set([50.192])           set([])
100406016   h2  set([50.192])           set([50.192])

我也尝试过 set_index,但那并不能适当地对数据框分组。

b=df.set_index(['user_nm','halves'])

这似乎是一个相对简单的任务,我错过了什么吗?
1个回答

8
这个问题的简短答案是,在缩小 groupby 对象时,需要使用 aggregate 方法。您可以查看Pandas GroupBy Aggregate以获取更多信息。
以下代码片段应该解决您的问题: 正确处理读取时的集合:元素将作为 str 而不是 set 输出。
df.unique_ips = df.unique_ips.apply(eval)
df.shifted_ips = df.shifted_ips.apply(eval)

进行分组操作
grouped = df.groupby(['user_nm', 'halves'])
my_lambda = lambda x: reduce(set.union, x)
output = grouped.aggregate({'unique_ips': my_lambda,
                            'shifted_ips': my_lambda})

结果是:
                             unique_ips            shifted_ips
user_nm   halves                                              
100118231 h1      set([142.136, 108.0])         set([142.136])
          h2      set([142.136, 108.0])  set([142.136, 108.0])
100406016 h1              set([50.192])                set([])
          h2              set([50.192])          set([50.192])

谢谢你,我知道我把这件事搞得比必要的还要困难。我要回到文档那里去了,感谢提供链接。 - Mike
2
很棒的解決方案,對於Python 3,您需要導入reduce:from functools import reduce - Matt
2
我建议使用my_lambda = lambda x: set.union(*x)代替functools.reduce。根据文档,自Python 2.6以来就可用。 - user21952-is-a-great-name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接