Вернуть строки, которые находятся на пересечении двух списков, используя функцию запроса в пандах - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть это df:

pd.DataFrame([[1, "type_1"], [2, "type_2"], [2, "type_1; type_2"], [2, "type_1; type_3"], [2, "type_3"], [2, "type_1; type_2, type_3"]],
                     columns=["a", "b"])
    a   b
0   1   type_1
1   2   type_2
2   2   type_1; type_2
3   2   type_1; type_3
4   2   type_3
5   2   type_1; type_2, type_3

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

my_list = ["type_1", "type_2"]
df.query("a == 2 and b in @my_list")

Теперь этоoutput:

    a   b
1   2   type_2

Но я бы хотел, чтобы вывод был таким, потому что хотя бы одно значение из b находится в my_list:

    a   b
0   2   type_2
1   2   type_1; type_2
2   2   type_1; type_3
3   2   type_1; type_2, type_3

Проблема, как вы можете видеть, заключается в том, что некоторые из моих столбцов на самом деле являются списками .На данный момент это строки, разделенные ;, но я могу преобразовать их в списки.Однако я не уверен, как это поможет мне отфильтровать строки, которые имеют хотя бы одно значение из column b внутри my_list , используя только .query () (потому что в противном случае мне придется анализировать запросстрока, и она становится грязной)

Это будет эквивалентный код со списками:

pd.DataFrame([[1, ["type_1"]], [2, ["type_2"]], [2, ["type_1", "type_2"]], [2, ["type_1", "type_3"]], [2, "type_3"], [2, ["type_1", "type_2", "type_3"]]],
                     columns=["a", "b"])

Ответы [ 2 ]

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

Вы можете использовать str.split перед повторным созданием списка в виде столбцов и использовать isin и any. Примечание isin - точное совпадение, что означает, что если вы наберете type_11, то при использовании isin это будетвозврат False

df[(pd.DataFrame(df.b.str.split(';').tolist()).isin(my_list).any(1))&(df.a==2)]
Out[88]: 
   a                       b
1  2                  type_2
2  2          type_1; type_2
3  2          type_1; type_3
5  2  type_1; type_2, type_3
0 голосов
/ 12 декабря 2018

На самом деле я был не прав.Похоже, что поддерживается с помощью механизма "python".

df.query("a == 2 and b.str.contains('|'.join(@my_list))", engine='python')

   a                       b
1  2                  type_2
2  2          type_1; type_2
3  2          type_1; type_3
5  2  type_1; type_2, type_3

(Старый ответ) Ваш запрос может быть разделен на две части: Часть, требующая проверки подстрокии все остальное.

Вы можете вычислить две маски отдельно.Я рекомендую использовать str.contains и DataFrame.eval.Затем вы можете И маски и фильтра df.

m1 = df.eval("a == 2")
m2 = df['b'].str.contains('|'.join(my_list))

df[m1 & m2]

   a                       b
1  2                  type_2
2  2          type_1; type_2
3  2          type_1; type_3
5  2  type_1; type_2, type_3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...