Python 这个还是那个

Python 这个还是那个,python,pandas,group-by,conditional-statements,pandas-groupby,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是同一个人,那么它也是同一个人。我想数一数每

请容忍我这件事,我已经为此伤了好几个小时了

以这些数据为例

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()
,因为它们应该返回相同的输出。 但是,addr
j
c
d
的身份输入了她的名字,而name
b
z
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')

但是我不知道如何使用它来执行
groupby
。我想尝试分配新的名称,可以正确识别重复的名称或地址,但不知道如何做到这一点。感谢您的帮助

如果我理解正确,您可以创建从地址到名称的映射。然后使用此映射覆盖名称,并正常执行
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
通过
addr
复制
首字母
drop\u,前提是为任何
名称
输入的第一个地址都是正确的。

另一种方法:

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
说明: 首先用于对
addr
col中的每组进行编号

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
然后使用name和sum
df.groupby('name',as_index=False)返回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或last
的函数来保留name的第一个/最后一个实例

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

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

你能详细说明一下这一机制吗?调用
ngroup()
“DataFrameGroupBy”对象没有属性“ngroup”
可能是我的熊猫:
pd.\uu version\uuuuuu Out[8]:“0.18.1”
?@GeneBurinsky是的。它仅在
版本0.20.2
中提供。您可以更新。@GeneBurinsky使用此
df['group']=df.groupby('addr').grouper.group_info[0]
而不是
df.groupby('addr').ngroup()
这是一个更快、更简单、也许更灵活的解决方案,但出于某种原因,@Abhi的解决方案可以找到更多的组。我认为这两个答案在应用于一个人的数据时都应该进行测试,因为根据复杂性,它们可能会产生不同的答案。