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

Это пример кадра данных, с которым я работаю:

df:

a      b     c
a1  P1,P3  abc
a2  P2,P4  def
a3  P2     ghi   `

Я хочу применить фильтры к нескольким столбцам в кадре данных, в котором есть значения, разделенные запятыми.

Данные фильтра представлены в виде series с именем df_filters, указанным ниже:

df_filters:
a    [a1]
b    [P1, P4]`

Данные фильтра содержат фрейм данных column name в виде string в первом столбце.и filter values как list во втором столбце.

Используя приведенный выше df_filters, отфильтруйте кадр данных df1 и получите следующий результат:

Result1:
a      b     c
a1  P1,P3  abc
a2  P2,P4  def  `

Вывод: для столбца a в df1 учитываются только те строки со значениемa1 и для столбца b учитываются только те строки, которые содержат значения P1 и P4.В столбце b строка 1, P1 и P3 - два разных значения с разделением запятыми.

Есть ли в любом случае, я могу достичь выше Result для df?

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

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Использование:

df_filters = pd.Series([['a1'], ['P1', 'P4'],['s']], index=['a','b','z'])
print (df_filters)
a        [a1]
b    [P1, P4]
z         [s]
dtype: object

#filter only matched columns
df_filters = df_filters.loc[df_filters.index.intersection(df.columns)]

#convert to set and get intersection of each value
from itertools import repeat
m = [[bool(set(a.split(',')).intersection(b)) for a, b in zip(df[i], repeat(j))] 
      for i, j in df_filters.items()]
print (m)
[[True, False, False], [True, True, False]]

#flatten boolean masks and filter
df = df[pd.np.logical_or.reduce(m)]
print (df)
    a      b    c
0  a1  P1,P3  abc
1  a2  P2,P4  def
0 голосов
/ 28 ноября 2018

Для каждого значения, которое вы проверяете, существует ли оно в соответствующем списке df_filters.Поскольку столбец может содержать список или отдельный элемент, он также должен проверить это.
Поскольку это условие немного сложное, я переместил эту логику в отдельную функцию _filter_func.

def _filter_func(x, f_vals_set):
    if not isinstance(x, list):
        # This is needed becouse values in dataframe could be single object or a list of objects
        x = [x]
    # Check if the there is any matching value in filter set
    matching_vals = f_vals_set.intersection(x)
    return len(matching_vals) > 0

conditions = [df[col].apply(lambda x: _filter_func(x, set(f_vals))) for col, f_vals in filters.items()]
df.loc[pd.np.logical_or.reduce(conditions)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...