TransWikia.com

Как отфильтровать pandas.DataFrame по столбцу, состоящему из списков в зависимости от наличия в списке тех или иных элементов?

Stack Overflow на русском Asked on November 29, 2021

Имеется pandas.DataFrame, в котором записана информация о школьных уроках и курсах. Среди неё имеется список классов, которые этот курс могут посещать (например, если это 9-11 класс, то будет записано [9, 10, 11] в типе int). Итак, предположим нужно получить список курсов, которые может посещать 8 класс. В Pandas это обычно делается с помощью булевского индексирования:

df = df[df['нужный_параметр'] == нужный_объект]

В результате часть df['нужный_параметр'] == нужный_объект возвращает список из значений True и False, где напротив каждого индекса указано, соответствует ли строка под этим индексом в DataFrame заданному параметру. Далее df[[bool-список]] возвращает только те значения, по индексу которых в bool-списке указано True.

Но как я писал выше, классы для посещения курсов записаны в списке из int, а не в str или int. Итак, пробуем:

df = df[8 in df['grades']]

В результате Python пожалуется с помощью KeyError на то, что df[] ожидал список из значений типа bool, что справедливо, ведь часть 8 in df['grades'] возвращает лишь один bool. Почему это происходит? Pandas образует bool-список только с мат. операторами и операторами сравнения строк? Плюс к тому же: в df['grades'] попросту нет значения 8; в этом столбце есть только списки, в которых имеется этот элемент ([8, ...]). Так почему же 8 in df['grades'] тогда возвращает True? Выходит, что df['grades'] возвращает список, в котором смешано содержимое всех списков столбца (и как в таком случае фильтровать DataFrame)?

Попробуем вручную создать этот самый bool-список и с его помощью отфильтровать DataFrame:

tf = []
for i in range(len(database['grades'])):
    if 8 in database['grades'][i]:
        tf.append(True)
    else:
        tf.append(False)
database = database[tf]

Это работает, но очевидно, что этот код громоздкий и возможно ресурсоёмкий. Как же привести всю эту обработку к удобному виду df = df[df['нужный_параметр'] == нужный_объект]? Если нет, как это привести к максимально удобному виду? Можно ли это сделать с помощью конструктора (tf = [i for i in ...])? Как завести этот самый список в отдельном столбце в DataFrame и как этот столбец быстро заполнить (я помню, что делал это, но сейчас забыл как)?

P. S. Понимаю, что возможно усложнил вопрос, но сделал его полным для получения полного ответа. Заранее благодарю, за то что прочитали всё и уделили вопросу внимание!

2 Answers

Пусть есть Dataframe:

            A
0    [3, 4, 5]
1  [9, 10, 11]

тогда:

num = 9
df["A"].apply(lambda x: num in x)

результат:

0    False
1     True
Name: A, dtype: bool

Answered by strawdog on November 29, 2021

Вроде бы можно только через lambda сделать, встроенной функции для этого не нашёл:

import pandas as pd

df = pd.DataFrame({'grades': [[9, 10, 11],[8, 10, 11],[8, 9]], 'something': [1,2,3]})
df[df.grades.apply(lambda x: 8 in x)]

Результат:

    grades      something
1   [8, 10, 11] 2
2   [8, 9]      3

Ответ подсмотрен на англоязычной части Stackoverflow

Answered by CrazyElf on November 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP