具有多个条件的Pandas Groupby

时间:2019-08-15 15:08:03

标签: python pandas

假设我有一个熊猫数据框,其中包含地址,名字和姓氏。我想基于这三个字段中的前三个字符对记录(行)进行分组。

例如,如果我们有

| index | address     | first_name | last_name |
|  1    | 1800 St.    | John       | Adams     |
|  2    | 1800 Street | J.         | A.        |
|  3    | Elm St.     | Junhui     | Wen       |
|  4    | NaN         | Jun        | W         |

然后

  • 记录1和2应该分组在一起(地址中3个字符)
  • 记录3和4应该分组在一起(名字中的相同3个字符)

在熊猫中,我知道可以用一栏来做到这一点:

data['3_char'] = data['address'].str[:3]
data.groupby('3_char').count().sort_values('index')['index']

但是您将如何通过所有三列上的OR条件将记录分组在一起?

2 个答案:

答案 0 :(得分:2)

您可以这样做:

df['g1'] = df.groupby(df['address'].str[:3]).ngroup()
df['g2'] = df.groupby(df['first_name'].str[:3]).ngroup()

输出:

  index      address first_name last_name  g1  g2
0     1     1800 St.       John     Adams   0   1
1     2  1800 Street         J.        A.   0   0
2     3      Elm St.     Junhui       Wen   1   2
3     4          NaN        Jun         W   2   2

答案 1 :(得分:1)

您可以通过一次折叠2列之间的连接来做到这一点。首先,我们分别为每一列创建不同的组,然后找出哪些标签成对连接

样本数据

       address first_name last_name
0     1800 St.       John     Adams
1  1800 Street        Jun        A.
2      Elm St.     Junhui       Wen
3          NaN         J.         W
4          111        foo     Adams

代码

import pandas as pd
import networkx as nx

# Label Each column separately
df['g1'] = 'A' + df.groupby(df['address'].str[:3]).ngroup().astype(str)
df['g2'] = 'B' + df.groupby(df['first_name'].str[:3]).ngroup().astype(str)
df['g3'] = 'C' + df.groupby(df['last_name'].str[:3]).ngroup().astype(str)

# Add the `|` condition for groups
for ga, gb in [('g1', 'g2'), ('g2', 'g3')]:
    G = nx.from_pandas_edgelist(df, ga, gb)
    # Find connections
    grps= [list(x.nodes) for x in nx.connected_component_subgraphs(G)]
    # Create new unique group id based on above connections
    d = {y: i for i in range(len(grps)) for y in grps[i]}
    # Replace group label so we can do this for the next pass.
    df[gb] = df[ga].map(d)

输出:

       address first_name last_name  g1  g2  g3
0     1800 St.       John     Adams  A1   0   0
1  1800 Street        Jun        A.  A1   0   0
2      Elm St.     Junhui       Wen  A2   0   0
3          NaN         J.         W  A3   1   1
4          111        foo     Adams  A0   2   0
g3中找到所需的 True 分组。 g1仅包含基于地址的分组。 g2是基于address | first_name(我们现在可以看到第三行和前两行已分组)。最后,g3现在是基于|的所有3列的分组,我们可以看到第5行是根据姓氏添加了前3行