当按panda中的其他列分组时,如何检查行是否以相同的值开头或包含相同的值



我有一个数据帧,我想按id和公共的"顶级"字符串进行分组,其中包括"低级"字符串的计数。例如,

id name
1  AA-BB-CC-DD
1  AA-BB-CC
1  AA-BB-CC-DD-EE
1  AA-BB-UU-VV
1  AA-BB-UU
1  FF-MM-NN
1  FF-MM-NN-PP
2  XX-YY
2  XX-ZZ
2  XX-ZZ-AA

对于id1,列名的第一个顶级是AA,第二个BB[/em>,第一个CC等等。数据帧中id 1的常见"最高"级别是AA-BB-CC//em>。

所需输出为

id  name      count
1   AA-BB-CC  3
1   AA-BB-UU  2
1   FF-MM-NN  2
2   XX-YY     1
2   XX-ZZ     2

谢谢。

IIUC,您可以使用第一个级别组成组,然后使用自定义函数groupby.agg

group = df['name'].str.extract('^([^-]+)', expand=False)
def min_string(s):
return min(s, key=lambda x: x.count('-'))
out = (df
.groupby(['id', group], as_index=False)
.agg(name=('name', min_string),
count=('name', 'count')
)
)

输出:

id      name  count
0   1  AA-BB-CC      3
1   1  FF-MM-NN      2
2   2     XX-YY      3

更新:处理第一级的最小集合

min_string更改为:

def min_string(s):
return '-'.join(x[0] for x in zip(*s.str.split('-'))
if len(set(x)) == 1)

示例输入:

id            name
0   1     AA-BB-CC-DD
1   1        AA-BB-CC
2   1  AA-BB-CC-DD-EE
3   1     AA-BB-UU-VV
4   1        AA-BB-UU
5   1        FF-MM-NN
6   1     FF-MM-NN-PP
7   2           XX-YY
8   2           XX-ZZ
9   2        XX-ZZ-AA

输出:

id      name  count
0   1     AA-BB      5
1   1  FF-MM-NN      2
2   2        XX      3

update2:最大公共子群

def make_groups(s, sep='-'):
d = {}
s = s.str.split(sep).sort_values()
prev = s.iloc[0]
for idx, val in s.items():
if val[:len(prev)] != prev:
prev = val
d[idx] = sep.join(prev)
return pd.Series(d, index=s.index)
group = df.groupby('id', group_keys=False)['name'].apply(make_groups)
out = (df
.groupby(['id', group], as_index=False)
.agg(name=('name', min_string),
count=('name', 'count')
)
)

输出:

id      name  count
0   1  AA-BB-CC      3
1   1  AA-BB-UU      2
2   1  FF-MM-NN      2
3   2     XX-YY      1
4   2     XX-ZZ      2

使用的输入:

id            name
0   1     AA-BB-CC-DD
1   1        AA-BB-CC
2   1  AA-BB-CC-DD-EE
3   1     AA-BB-UU-VV
4   1        AA-BB-UU
5   1        FF-MM-NN
6   1     FF-MM-NN-PP
7   2           XX-YY
8   2           XX-ZZ
9   2        XX-ZZ-AA

最新更新