У меня есть фреймворк pandas. Я хочу выбрать значения из col1, которые должны иметь все 3 значения в col2.
col2_values_should start_with = [P1.adv, P2.cmp, P3.part ]
Кроме того, поскольку вы можете видеть более позднюю часть значений в col2, это фиктивная часть. поэтому мне нужно использовать такую же опцию, как оператор LIKE SQL, чтобы проверить значения col2.
поэтому ответ из приведенной выше таблицы:
потому что "A" имеет все три требуемые значения, в отличие от B и C.
Итак, в основном я хочу проверить, какое значение в col1 имеет все 3 требуемые значения в col2. и эти значения col2 должны начинаться с определенных букв, как указано выше.
Редактировать:
Пример данных
ID col1 col2
1 A P1.adv abcd
2 А P2.cmp mkmfwk
3 A P3.part lpwf
4 Б P1.adv abcd
5 Б P2.cmp mkmfwk
6 C P1.addv abcd
7 C P1.adv abcd
Используйте 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
Я не думаю, что OP хочет этого
@jezrael - это не повторяющийся вопрос. Мне нужно ограничить, если col1 имеет определенные значения в col2 (не каждое значение в col2)
Во втором решении я получаю ошибку памяти. Однако в вашем 1-м решении не могли бы вы сказать, нет ли скобок?
@frozenshine - у меня все работает нормально, у вас есть синтаксическая ошибка?
@frozenshine - добавлено альтернативное решение, надеюсь без ошибок памяти.
Я бы предложил использовать регулярное выражение и подсчитывать количество случаев, когда 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
Вот как это сделать:
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
Создайте временный столбец в фрейме данных, который проверяет, присутствует ли какой-либо целевой префикс в col2. Затем сгруппируйте их по столбцу 1 и сумме. Затем проверьте, равна ли сумма 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
предоставьте образцы данных в текстовом формате, иначе вам будет сложнее помочь