кадр данных панд, сравнивающий строковые значения для 2 групп по столбцам - PullRequest
3 голосов
/ 23 октября 2019

У меня есть набор данных, который выглядит следующим образом:

ID        Search    Provider
1           Yes     A
1           Yes     B
1           No      B
1           No      C
2           Yes     D
2           Yes     A
2           Yes     B
2           No      B
2           No      C

Я хочу выяснить, отличается ли провайдер для Search==Yes от Search==No для данного идентификатора. Например, «ID 1», «Поиск = Нет» переходит к провайдерам B, C, тогда как «Поиск = Да» переходит к провайдерам A, B. Таким образом, поставщик А является новым для идентификатора 1.

Я знаю, что могу использовать функцию isin для определения уникальных значений между двумя списками. Тем не менее, как мне сделать это через несколько строк ID и поиска? И как мне скомпилировать значения провайдера в списки для каждой подгруппы, определенной с помощью идентификатора и поиска? Я думаю, мне нужно будет использовать вложенные циклы, но я не смог написать код. Буду очень признателен, если кто-нибудь сможет мне помочь в этом.

Ответы [ 3 ]

1 голос
/ 23 октября 2019

Вместо того, чтобы компилировать в списки, вы можете рассмотреть наборы. В общем смысле это может быть более полезным, поскольку я предполагаю, что порядок и избыточность не имеют значения. Кроме того, легче определить, какие провайдеры входят в один набор, а не в другой. Вы можете переставить свой фрейм данных с помощью pivot_table, чтобы сделать это:

df_new = df.pivot_table(index='ID', columns='Search', aggfunc=set).droplevel(0, axis=1)

Результат:

Search      No        Yes
ID                       
1       {C, B}     {A, B}
2       {C, B}  {D, A, B}

С этим новым фреймом данных вы можете сравнивать значения с тем же «ID», что и просто:

# df_new['No'] == df_new['Yes']   # If providers are the same between "yes" and "no"
df_new['Yes'] - df_new['No']      # Providers that are in "yes" but not "no"

Результат (для заданной разности):

ID
1       {A}
2    {D, A}
dtype: object
0 голосов
/ 23 октября 2019

Метод 1

Сначала можно использовать groupby.agg(set), затем снова groupby.diff:

dfg = df.groupby(['ID', 'Search']).agg(set).reset_index()
dfg.groupby('ID')['Provider'].diff().dropna()

1       {A}
3    {A, D}
Name: Provider, dtype: object`

Метод 2

Разделение набора данных на yes и no, затем groupby.set:

yes = df.loc[df['Search'] == 'Yes']
no  = df.loc[df['Search'] == 'No']

yes_agg = yes.groupby('ID')['Provider'].agg(set)
no_agg = no.groupby('ID')['Provider'].agg(set)

# get the difference between the sets
yes_agg - no_agg

ID
1       {A}
2    {A, D}
Name: Provider, dtype: object
0 голосов
/ 23 октября 2019

Это можно сделать за несколько шагов. Сначала сгруппируйте по идентификатору и выполните поиск, а затем получите уникальные значения с помощью value_counts.

>>> df1 = df.groupby(['ID', 'Search']).Provider.value_counts()
ID  Search  Provider
1   No      B           1
            C           1
    Yes     A           1
            B           1
2   No      B           1
            C           1
    Yes     A           1
            B           1
            D           1

Для каждой комбинации идентификатора / провайдера вы можете получить счетчик числа запросов Да / Нет

>>> df2 = df1.unstack(level='Search', fill_value=0)
Search       No  Yes
ID Provider         
1  A          0    1
   B          1    1
   C          1    0
2  A          0    1
   B          1    1
   C          1    0
   D          0    1

Отсюда вы можете получить список комбинаций провайдеров / идентификаторов, которые имеют либо Да, либо Нет, но не оба

>>> df2 = df1.query('Yes != No')
Search       No  Yes
ID Provider         
1  A          0    1
   C          1    0
2  A          0    1
   C          1    0
   D          0    1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...