假设我有一个熊猫数据框,其中包含地址,名字和姓氏。我想基于这三个字段中的前三个字符对记录(行)进行分组。
例如,如果我们有
| 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 |
然后
在熊猫中,我知道可以用一栏来做到这一点:
data['3_char'] = data['address'].str[:3]
data.groupby('3_char').count().sort_values('index')['index']
但是您将如何通过所有三列上的OR条件将记录分组在一起?
答案 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行