仅按“ [3个值的列表]”这样的值分组

时间:2018-12-18 14:08:24

标签: python-3.x pandas dataframe group-by

我有熊猫数据框。我想从col1中选择值,该值应在col2中具有所有3个值。 col2_values_should start_with = [P1.adv, P2.cmp, P3.part ]  另外,由于您可以在col2中看到值的后面部分,因此是虚拟的。因此我需要使用与SQL的LIKE运算符类似的选项来检查col2值。

enter image description here

所以上表的答案是:

enter image description here

因为与B和C不同,“ A”具有所有必需的三个值。

所以基本上我想检查col1中的哪个值在col2中具有所有3个必需值。这些col2值应以上述某些字母开头。

编辑:

样本数据

ID col1 col2

1 A P1.adv abcd

2 A P2.cmp mkmfwk

3 A P3.part lpwf

4 B P1.adv abcd

5 B P2.cmp mkmfwk

6 C P1.addv abcd

7 C P1.adv abcd

4 个答案:

答案 0 :(得分:2)

这是一种方法:

l = ('P1.adv', 'P2.cmp', 'P3.part' )
m1 = df.groupby('col1').apply(lambda x: x.col2.str.startswith(l, na=False)).reset_index()
m2 = df[m1.col2].groupby('col1').col2.nunique() > 2
df[df.col1.isin(m2[m2].index.values)]

   ID  col1         col2
0   1    A   P1.adv abcd
1   2    A  P2.cmp kmasd
2   3    A   P3.part lpw

说明

您可以先使用str.startswith检查df中的哪些行包含以列表中的一项开头的col2

print(m1)

 col1  level_1  col2
0    A        0  True
1    A        1  True
2    A        2  True
3    B        3  True
4    B        4  True
5    C        5  True
6    C        6  True

使用GroupBy.nunique()分组col1并检查唯一项的数量是否大于2(意味着列表中的每个元素至少存在一次)之后:

print(m2)

col1
A     True
B    False
C    False
Name: col2, dtype: bool

最后使用df在原始m2上使用布尔索引:

result = df[df.col1.isin(m2[m2].index.values)]
print(result)

    ID  col1        col2
0   1    A   P1.adv abcd
1   2    A  P2.cmp kmasd
2   3    A   P3.part lpw

答案 1 :(得分:1)

extract与正则表达式一起使用,其中^用于字符串的匹配开始,|用于OR,然后将groupbytransform并比较{ {1}} s,也正在比较是否像set这样的组长:

list

另一种解决方案是按startswith过滤,然后与size进行计数计数,按nunique获得唯一值的数量,并按列表长度进行比较,最后按{{3}进行过滤}},并用L = ["P1.adv", "P2.cmp", "P3.part"] pat = '|'.join(r"^{}".format(x) for x in L) s = df['col2'].str.extract('('+ pat + ')', expand=False) df = df[s.groupby(df['col1']).transform(lambda x: set(x) == set(L) and len(x) == len(L))] print (df) ID col1 col2 0 1 A P1.adv abcd 1 2 A P2.cmp mkmfwk 2 3 A P3.part 1pwf 检查两个值是否均为all

True

答案 2 :(得分:0)

我建议使用正则表达式并计算A的出现次数等于[模式匹配

import pandas as pd
df = pd.DataFrame({'a':[1,2,1,1,5,5],'b':["abc.more","abcde.kef","abc.mop","lop.e","lop.e","get.le"]})
con = df.b.str.match('^(abc.m|lop.e)')
df['c'] = con
df['sum_c'] = df.groupby('a')['c'].transform('sum')
df['count_a'] = df.groupby('a')['a'].transform('count')
dff = df[df['count_a']==df['sum_c']]
dff

答案 3 :(得分:0)

在数据框中创建一个临时列,以检查col2中是否存在任何目标前缀。然后将它们按col1求和。然后检查总和是否等于3

ans = (df.assign(temp = df.col2.str.startswith(tuple(col2_values_should_start_with)))\
         .groupby('col1')[['temp']].sum() == 3).reset_index()

最后,找到具有3个起始字符串的col1的值

df[df['col1'].isin(list(ans[ans.temp == True].col1))]

输出:

    ID   col1       col2
    1    A    P1.advabcd
    2    A  P2.cmpmkmfwk
    3    A   P3.partlpwf