Группировка столбца с помощью логического сравнения (аналогично использованию grpstats Matlab)

#python #pandas

#python #pandas

Вопрос:

У меня есть фрейм данных в Pandas, который имеет следующий формат (также с кучей других столбцов)

    chip  WL     ok
0     1   1   True
1     1   2   True
2     1   3   True
3     1   4   True
4     2   1  False
5     2   2   True
6     2   3   True
7     2   4   True
  

Я хочу сгруппировать по чипам, подсчитать количество WLS для каждого chip и выполнить логическую and обработку каждого значения в ok столбцах. Ожидаемый результат должен выглядеть следующим образом:

    chip  WLs     ok
0     1   4    True
1     2   4   False
  

В Matlab это было бы достигнуто с помощью следующей команды:

 a = grpstats(CellYield,{'chip'},{@all},'DataVars',{'ok'});
a.Properties.VarNames{2} = 'WLs';
a.Properties.VarNames{3} = 'ok';
  

Который будет выводить набор данных, подобный этому:

 chip WLs    ok
1    4      True
2    4      False
  

Как мне это сделать в Python и Pandas?

Ответ №1:

Используйте groupby , и мы можем передать набор функций для применения к каждому столбцу, для WL столбца, который мы применяем count из pandas.Series , all применяет тест ко всем значениям и возвращает, True если все значения в ряду равны True и False в противном случае.

 In [6]:

df.groupby('chip').agg({'WL':pd.Series.count, 'ok':all})

Out[6]:
      WL     ok
chip           
1      4   True
2      4  False

[2 rows x 2 columns]
  

Обновить

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

Таким образом, вы можете вместо этого сделать это за 2 прохода следующим образом:

 In [30]:

df['WL'] = df.groupby('chip')['WL'].transform('count')
df['ok'] = df.groupby('chip')['ok'].transform('all')
df
Out[30]:
       chip  WL     ok    foo    bar
index                               
0         1   4   True  hello  world
1         1   4   True  hello  world
2         1   4   True  hello  world
3         1   4   True  hello  world
4         2   4  False  hello  world
5         2   4  False  hello  world
6         2   4  False  hello  world
7         2   4  False  hello  world

[8 rows x 5 columns]
  

Комментарии:

1. Спасибо, это работает. Есть ли какой-либо способ передавать столбцы без каких-либо изменений в aggregate? Например, у меня есть несколько дополнительных столбцов, содержащих строки. Они одинаковы для всех вариантов использования. Я хочу, чтобы на выходе были столбцы [chip, wl, foo, bar, ok], в которых не было внесено изменений в foo и bar. Как это можно сделать? Foo и bar одинаковы для всех записей.

2. звучит так, как будто вы хотите, transform это вернет объект, который индексируется так же, как исходный df, я не знаю, будет ли он принимать agg функции, я не могу заставить это работать, возможно, опубликовать как другой вопрос, специфичный для этого требования

3. @veor Я нашел способ сделать это, дважды вызвав transform дайте мне знать, отвечает ли это на ваш вопрос, и если да, вы можете принять в качестве ответа, нажав на пустую галочку под стрелками голосования