У меня есть датафрейм, который вы можете построить с этим:

dflist=[['123',['abc','qw3','123']],
        ['ab12',['3e4r5','12we3','asd23','q2w3']]]
df=pd.DataFrame(dflist,columns=['check','checklist'])

И выглядит так:

  check                    checklist
0   123              [abc, qw3, 123]
1  ab12  [3e4r5, 12we3, asd23, q2w3]

Я хочу проверить, есть ли пункт в столбце «проверка» в списке в столбце «контрольный список». Поэтому я хочу, чтобы итоговый кадр данных выглядел следующим образом:

  check                    checklist checkisin
0   123              [abc, qw3, 123]      True
1  ab12  [3e4r5, 12we3, asd23, q2w3]     False

Я пробовал несколько вещей, включая использование .isin в различных формах, включая apply / lambda. и напрямую.

Этот:

df['checkisin']=df.check.isin(df.checklist)

Производит:

  check                    checklist  checkisin
0   123              [abc, qw3, 123]      False
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

Который имеет два ложных.

Попытка этого: df ['checkisin'] = df.apply (лямбда-x: x.check.isin (x.checklist)) выдает эту ошибку:

AttributeError: ("'Series' object has no attribute 'check'", 'occurred at index check')

Пробую это:

df['checkisin']=df.apply(lambda x:x['check'] in x.checklist)

Выдает эту ошибку:

KeyError: ('check', 'occurred at index check')

Я уверен, что мне здесь не хватает чего-то простого. Я знаю, что мог бы зациклить это, но ищу мудрое решение Pandas Dataframe, так как у меня очень большой DF, и он пытается «наиболее» эффективно справиться.

Спасибо!

7
clg4 30 Июн 2019 в 04:55

4 ответа

Лучший ответ

У вас есть столбец списков, конечно, у pandas нет функций, которые изначально поддерживают операции с данными, структурированные так плохо. Если вы хотите наибольшую производительность, я бы порекомендовал понимание списка:

df['checkisin'] = [c in l for c, l in zip(df['check'], df['checklist'])]
df
  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

Вы можете рассмотреть возможность реализации обработки ошибок, за исключением случаев, когда вы беспокоитесь о NaN и несоответствиях типов:

def check_isin(check, checklist):
    try:
        return check in checklist
    except TypeError:
        return np.NaN

df['checkisin'] = [
    check_isin(c, l) for c, l in zip(df['check'], df['checklist'])
]

Свидетельства свидетельствуют о том, что списки являются наиболее желательным вариантом для операций, которые не может быть векторизовано.

PS, рассмотрите возможность преобразования вашего столбца списков в столбец наборов, если вы планируете много проверять членство.


Вот пример того, как эта операция может быть векторизована.

from itertools import chain

cl = df.pop('checklist')
df = (pd.DataFrame(df.reset_index().values.repeat(cl.str.len(), axis=0), 
                   columns=['group', *df.columns])
        .assign(checklist=list(chain.from_iterable(cl))))

df

   group check checklist
0      0   123       abc
1      0   123       qw3
2      0   123       123
3      1  ab12     3e4r5
4      1  ab12     12we3
5      1  ab12     asd23
6      1  ab12      q2w3
7      1  ab12       123

(df['check'] == df['checklist']).groupby(df.group).any()

group
0     True
1    False
dtype: bool
5
cs95 30 Июн 2019 в 20:52

Я буду использовать isin с Series, isin с Series будет сначала соответствовать index, который отличается от list

pd.DataFrame(df.checklist.tolist(),index=df.index).isin(df.check).any(1)
Out[496]: 
0     True
1    False
dtype: bool

Или же

pd.DataFrame(df.checklist.tolist(),index=df.index).eq(df.check,0).any(1)
4
YO and BEN_W 30 Июн 2019 в 02:05

Вы можете попробовать:

df['checkisin'] = [v in df.checklist[i] for i, v in enumerate(df.check)]

Или же:

df['checkisin'] = [i in j for i, j in zip(df.check, df.checklist)]

Или же:

df['checkisin'] = list(map(lambda i, j: i in j, df.check, df.checklist))

Или (когда вы предпочитаете df.assign):

df.assign(checkisin=[*map(lambda i, j: i in j, df.check, df.checklist)])

Результат:

  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False
1
Rene 30 Июн 2019 в 09:09

map

df.assign(checkisin=[*map(lambda s, x: s in x, *map(df.get, df))])

  check                    checklist  checkisin
0   123              [abc, qw3, 123]       True
1  ab12  [3e4r5, 12we3, asd23, q2w3]      False

Если ваш фрейм данных имеет больше столбцов, вы можете быть более явным

cols = ['check', 'checklist']
df.assign(checkisin=[*map(lambda s, x: s in x, *map(df.get, cols))])
4
piRSquared 30 Июн 2019 в 03:30