сгруппировать только те значения, которые похожи на «[список из 3 значений]» - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть пандас датафрейм.Я хочу выбрать значения из col1, которые должны иметь все 3 значения в col2.col2_values_should start_with = [P1.adv, P2.cmp, P3.part ] Кроме того, поскольку вы можете видеть более позднюю часть значений в столбце col2, это пустышка.поэтому мне нужно использовать опцию, аналогичную оператору LIKE в SQL, чтобы проверить значения col2.

enter image description here

, поэтому ответ из приведенной выше таблицы:

enter image description here

, потому что "A" имеет все три требуемых значения, в отличие от B & C.

Поэтому в основном я хочу проверить, какое значение вcol1 имеет все 3 обязательных значения в col2.и эти значения 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 голосов
/ 18 декабря 2018

Создать временный столбец в кадре данных, который проверяет, присутствует ли какой-либо из префиксов назначения в col2.Затем сгруппируйте их по col1 и сумме.Затем проверьте, равна ли сумма 3

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

Наконец, найдите значение col1, содержащее 3 начальные строки

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
0 голосов
/ 18 декабря 2018

Я бы предложил использовать регулярное выражение и подсчитать число случаев, когда 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
0 голосов
/ 18 декабря 2018

Вот способ сделать это:

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

Объяснение

Вы можете начать с проверки того, какие строки в df содержат col2, который начинаетсяс одним из элементов в списке, используя str.startswith.

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

После того, как вы можете сгруппировать col1 и проверить, что количество уникальных элементов больше 2 (это означает, чтокаждый из элементов в списке присутствует хотя бы один раз), используя GroupBy.nunique():

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

0 голосов
/ 18 декабря 2018

Используйте extract с регулярным выражением с ^ для начала соответствия строки и | для OR, затем groupby с transform и сравнение set s, также сравнивает, если такая же длина групп, как list:

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

Другим решением является фильтрация по startswith, затем агрегирование сsize для счетчиков, получить число уникальных значений по nunique и сравнить оба по длине списка, последний фильтр по boolean indexing с all для проверки, являются ли оба значения True с:

df = df[df['col2'].str.startswith(tuple(L))].copy()
m = df.groupby('col1')['col2'].agg(['size','nunique']) == len(L)
df = df[df['col1'].isin(m.index[np.all(m, axis=1)])]
print (df)
   ID col1           col2
0   1    A    P1.adv abcd
1   2    A  P2.cmp mkmfwk
2   3    A   P3.part 1pwf
...