Группировка и поворот DataFrame с дополнительным столбцом для соотношения количества - PullRequest
0 голосов
/ 19 декабря 2018

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

id       status      year 
1        yes         2014
3        no          2013
2        yes         2014
4        no          2014

Реальный фрейм данных очень большой с несколькими идентификаторами и годами.Я пытаюсь создать новый фрейм данных с процентами «да» и «нет», сгруппированных по годам.

Я думал о том, чтобы сгруппировать фрейм данных по годам, который затем поместил бы в список статусы по годам, а затем проанализировать число «да» и «нет» таким образом, но мне было интересно, есть ли более питоническийспособ сделать это?

Я бы хотел, чтобы конечный кадр данных выглядел так:

year      yes_count     no_count     ratio_yes_to_toal    
2013       0             1             0%
2014       2             1             67%

Ответы [ 4 ]

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

pd.crosstab

Вы можете создать кросс-таблицу своего информационного кадра, а затем рассчитать свой коэффициент:

res = pd.crosstab(df['year'], df['status'])
res['yes_pct'] = res['yes'].div(res.sum(1))

print(res)

status  no  yes   yes_pct
year                     
2013     1    0  0.000000
2014     1    2  0.666667
0 голосов
/ 19 декабря 2018

Чтобы получить количество и проценты, вероятно, проще всего сделать это в два шага с помощью groupby + value_counts + unstack с последующим делением.

df1 = df.groupby('year').status.value_counts().unstack(1).fillna(0)
df1['ratio_yes'] = df1['yes'].div(df1.sum(1), axis=0)*100

#status   no  yes  ratio_yes
#year                       
#2013    1.0  0.0   0.000000
#2014    1.0  2.0  66.666667

Если выпросто хотите проценты, тогда вы можете добавить аргумент normalize=True и сделать это за один шаг:

df1 = df.groupby('year').status.value_counts(normalize=True).unstack(1).fillna(0)*100

#status          no        yes
#year                         
#2013    100.000000   0.000000
#2014     33.333333  66.666667
0 голосов
/ 19 декабря 2018

Вы можете использовать pivot_table без группировки для более быстрого решения.

v = df.pivot_table(index='year', columns='status', aggfunc='size').fillna(0) 
v.join((v['yes'] / v.sum(1)).to_frame('ratio'))
# Or, if you care about micro-optimizing the code, 
# v['ratio'] = v['yes'] / v.sum(1)

       no  yes     ratio
year                    
2013  1.0  0.0  0.000000
2014  1.0  2.0  0.666667
0 голосов
/ 19 декабря 2018

Я бы предложил сгруппировать по year и status, сосчитать, повернуть, а затем создать дополнительный столбец с соотношением:

df2 = df.groupby(['year', 'status']).count().pivot_table(index="year", columns=["status"]).fillna(0)
df2.columns = df2.columns.get_level_values(1)
df2['ratio'] = df2['yes'] / (df2['yes'] + df2['no'])

Вывод

status   no  yes     ratio
year                      
2013    1.0  0.0  0.000000
2014    1.0  2.0  0.666667
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...