Перебор результатов value_counts() для объекта groupby

#python #pandas

#python #панды

Вопрос:

У меня есть такой фрейм данных, как . df = pd.DataFrame({'ID':[1,1,2,2,3,3,4,4,5,5,5],'Col1':['Y','Y','Y','N','N','N','Y','Y','Y','N','N']}) Что я хотел бы сделать, это сгруппировать по столбцу ‘ID’, а затем получить статистику по трем условиям:

  1. Сколько групп имеют только ‘Y
  2. Сколько групп имеют не менее 1 ‘Y’ и не менее 1 ‘N’
  3. Сколько групп имеют только ‘N

groups = df.groupby('ID') groups.Col1.value_counts()

дает мне визуальное представление о том, что я ищу, но как я могу затем перебирать результаты метода value_counts() для проверки этих условий?

Ответ №1:

Я думаю pd.crosstab() , может быть более подходящим для вашего варианта использования.

Код

 df_crosstab = pd.crosstab(df["ID"], df["Col1"])

Col1  N  Y
ID        
1     0  2
2     1  1
3     2  0
4     0  2
5     2  1
 

Groupby также может выполнять эту работу, но гораздо более утомительно:

 df_crosstab = df.groupby('ID')["Col1"]
   .value_counts()
   .rename("count")
   .reset_index()
   .pivot(index="ID", columns="Col1", values="count")
   .fillna(0)
 

Фильтрация групп

После создания df_crosstab можно легко создать фильтры для ваших 3 вопросов:

 # 1. How many groups have only 'Y's
df_crosstab[df_crosstab['N'] == 0]

Col1  N  Y
ID        
1     0  2
4     0  2

# 2. How many groups have at least 1 'Y' and at least 1 'N'
df_crosstab[(df_crosstab['N'] > 0) amp; (df_crosstab['Y'] > 0)]

Col1  N  Y
ID        
2     1  1
5     2  1

# 3. How many groups have only 'N's
df_crosstab[df_crosstab['Y'] == 0]

Col1  N  Y
ID        
3     2  0
 

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

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

1. Спасибо, что поделились хорошим ответом с хорошим объяснением.

Ответ №2:

 groups = df.groupby('ID')  
answers = groups.Col1.value_counts()

for item in answers.iteritems(): 
    print(item) 
 

То, что вы создаете, — это серия, из value_counts() которой вы можете перебирать их. Обратите внимание, что это не то, что вы хотите. Вам нужно будет проверить каждый из этих элементов на наличие тестов, которые вы ищете.

Ответ №3:

Если вы группируете по ‘ID’ и используете функцию ‘sum’, у вас будут все буквы в одной строке для каждой группы. Затем вы можете просто посчитать строки, чтобы проверить свои условия, и взять их суммы, чтобы узнать точные числа для всех групп:

 strings = df.groupby(['ID']).sum()

only_y = sum(strings['Col1'].str.count('N') == 0)
only_n = sum(strings['Col1'].str.count('Y') == 0)
both = sum((strings['Col1'].str.count('Y') > 0) amp; (strings['Col1'].str.count('N') > 0))

print('Number of groups with Y only: '   str(only_y), 
      'Number of groups with N only: '   str(only_n), 
      'Number of groups with at least one Y and one N: '   str(both), 
      sep='n')