通过这个或那个分组

时间:2018-10-17 23:39:36

标签: python pandas group-by conditional-statements pandas-groupby

为此,我忍受了好几个小时。

考虑这些数据

np.random.seed(2)
apples = np.random.randint(10,20,9)
df = pd.DataFrame({'name':list('aabbcdeee'), 'addr':list('mmznjjkkx'), 'apples':apples})[['name','addr','apples']]

如果name是同一个人,则是同一个人,如果addr是同一个人,则也是同一个人。我想计算每个人的苹果数量。通常,这是微不足道的:

In [50]: df[['apples', 'name']].groupby('name').sum()
    Out[50]:
      apples
name
a         36
b         28
c         18
d         17
e         38

df[['apples', 'addr']].groupby('addr').sum(),因为它们应该返回相同的输出。 ,地址j输入了她的名字cd,而名字b输入了她的地址z和{{ 1}},而n正确输入了两次地址,但第三次却弄乱了。结果,上述两个e操作都会计数不足一些人拥有的苹果数量。理想的输出是:

groupby

我可以使用集合来标识具有错误地址或名称的索引:

In [52]: %paste
pd.DataFrame({'name':list('aabbcceee'), 'addr':list('mmnnjjkkk'), 'apples':apples}).groupby('name').apples.sum()

## -- End pasted text --
Out[52]:
name
a    36
b    28
c    35
e    38
Name: apples, dtype: int32

这样,错误就在这里:

sameNames = df.name[df.name.duplicated()].index
sameAddr = df.addr[df.addr.duplicated()].index
sameNameORaddr = df.name[(df.name.duplicated() | df.addr.duplicated())].index

但是我不知道如何使用它来执行In [47]: sameNameORaddr.difference(sameNames).union(sameNameORaddr.difference(sameAddr)) Out[47]: Int64Index([2, 3, 4, 5, 8], dtype='int64') 。我正在考虑尝试分配新名称,这些新名称可以正确识别重复的名称或地址,但无法弄清楚该怎么做。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

另一种方法:

df['group'] = df.groupby('addr').ngroup()

d = {'name':'first','apples':'sum'}
df1 = df.groupby('name',as_index=False).sum().groupby('group').agg(d)

df1 = df1.sort_values('name').reset_index(drop=True)

print (df1)

# Output:

  name  apples
0   a    36
1   b    28
2   c    35
3   e    38

说明:

首先使用groupby.ngroupaddr列中的每个组编号

df['group'] = df.groupby('addr').ngroup()

  name addr apples group
0   a   m    18     2
1   a   m    18     2
2   b   z    16     5
3   b   n    12     3
4   c   j    18     0
5   d   j    17     0
6   e   k    12     1 
7   e   k    11     1 
8   e   x    15     4

然后使用名称和总和df.groupby('name',as_index=False).sum()的groupby返回

   name  apples group
 0  a     36     4
 1  b     28     8
 2  c     18     0
 3  d     17     0
 4  e     38     6

现在,相同的地址行将具有相同的组号,因此您再次在group列上进行分组,并使用apples = 'sum'name = first or last的{​​{3}}函数来保持第一个/最后一个名称实例。

d = {'name':'first','apples':'sum'}
df1 = df.groupby('name',as_index=False).sum().groupby('group').agg(d)

然后仅对值进行排序并重置索引以获取输出。

答案 1 :(得分:1)

如果我理解正确,则可以创建从地址到名称的映射。然后使用此映射覆盖名称,然后像平常一样执行GroupBy

s = df.drop_duplicates('addr').set_index('addr')['name']
df['name'] = df['addr'].map(s)

res = df.groupby('name', as_index=False)['apples'].sum()

print(res)

  name  apples
0    a      36
1    b      28
2    c      35
3    e      38

drop_duplicates开头的addr假设输入的name first 地址是正确的地址。