Как построить гистограмму с накоплением с помощью pandas python

У меня есть 3 фрейма данных для годовых данных (по одному за 2014, 2015 и 2016 годы), каждый из которых имеет 3 столбца с именем 'PRACTICE', 'BNF NAME', 'ITEMS'.

BNF NAME относится к названиям лекарств, и я выбираю 3 ампициллина, амоксициллин и ко-амоксиклав. В этом столбце указаны разные силы / дозировки (например, Ко-Амоксиклав 200 мг или Ко-Амоксиклав 300 мг и т. Д.), Которые я хочу игнорировать, поэтому я использовал str.contains(), чтобы выбрать эти 3 препарата. ITEMS - общее количество рецептов, выписанных на каждый препарат.

Я хочу создать столбчатую диаграмму с накоплением, где по оси X будет указан год (2014, 2014, 2015), а по оси Y - общее количество рецептов, а каждая из 3 полосок будет разделена на 3 для каждого названия лекарства.

Я предполагаю, что мне нужно использовать df.groupby() и, возможно, выбрать частичную строку, однако я не уверен, как объединить годовые данные, а затем как сгруппировать данные для создания столбчатой ​​диаграммы с накоплением.

Будем очень признательны за любое руководство.

Это строка кода, которую я использую для выбора строк только для трех названий лекарств.

frame=frame[frame['BNF NAME'].str.contains('Ampicillin' and 'Amoxicillin' and 'Co-Amoxiclav')] 

Вот на что похож каждый из фреймов данных:

PRACTICE |  BNF NAME |  ITEMS
Y00327 | Co-Amoxiclav_Tab 250mg/125mg | 23
Y00327 | Co-Amoxiclav_Susp 125mg/31mg/5ml S/F | 10
Y00327 | Co-Amoxiclav_Susp 250mg/62mg/5ml S/F | 6
Y00327 | Co-Amoxiclav_Susp 250mg/62mg/5ml | 1
Y00327 | Co-Amoxiclav_Tab 500mg/125mg | 50

person Louise Stevens    schedule 27.11.2016    source источник
comment
Чтобы упростить построение графика, вы, вероятно, захотите объединить три фрейма данных в один. Если вы опубликуете небольшую часть фактических данных (frame.head(5).to_dict()), мы сможем помочь вам быстрее.   -  person DataSwede    schedule 27.11.2016
comment
@DataSwede Я предполагаю, что это использует pd.concat ()? См. Снимок добавленных мной макетов фреймов данных.   -  person Louise Stevens    schedule 27.11.2016
comment
@DataSwede Когда я пробую это, полученная гистограмма не складывается, т.е. она похожа на стандартную гистограмму только с одним лекарством (Ко-амоксиклав) .. любые идеи относительно того, почему? Я добавил .fillna (False), чтобы иметь дело с отсутствующими значениями - не уверен, связано ли это с этим?   -  person Louise Stevens    schedule 28.11.2016
comment
@DataSwede - эта строка кода .. 'frame = frame [frame [' BNF NAME ']. Str.contains (' Ampicillin 'and' Amoxicillin 'and' Co-Amoxiclav ')]' для выбора 3 препаратов не работает ... есть идеи, как выбрать эти 3 подстроки?   -  person Louise Stevens    schedule 28.11.2016


Ответы (1)


Вероятно, будет несколько разных способов добиться этого. Вот как бы я это сделал. Я использую блокнот jupyter, поэтому импорт в matplotlib может отличаться.

import pandas as pd
%matplotlib
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')

df = pd.DataFrame({'PRACTICE': ['Y00327', 'Y00327', 'Y00327', 'Y00327', 'Y00327'],
                   'BNF NAME': ['Co-Amoxiclav_Tab 250mg/125mg', 'Co-Amoxiclav_Susp 125mg/31mg/5ml S/F',
                                'Co-Amoxiclav_Susp 250mg/62mg/5ml S/F', 'Ampicillin 250mg/62mg/5ml',
                               'Amoxicillin_Tab 500mg/125mg'],
                   'ITEMS': [23, 10, 6, 1, 50]})



Out[52]:
BNF NAME    ITEMS   PRACTICE
0   Co-Amoxiclav_Tab 250mg/125mg    23  Y00327
1   Co-Amoxiclav_Susp 125mg/31mg/5ml S/F    10  Y00327
2   Co-Amoxiclav_Susp 250mg/62mg/5ml S/F    6   Y00327
3   Ampicillin 250mg/62mg/5ml   1   Y00327
4   Amoxicillin_Tab 500mg/125mg 50  Y00327

Чтобы смоделировать ваши три фрейма данных:

df1 = df.copy()
df2 = df.copy()
df3 = df.copy()

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

df1['YEAR'] = 2014
df2['YEAR'] = 2015
df3['YEAR'] = 2016

Объединение трех фреймов данных:

combined_df = pd.concat([df1, df2, df3], ignore_index=True)

Чтобы указать, какое лекарство представляет каждая строка:

combined_df['parsed_drug_name'] = "" # creates a blank column
amp_bool = combined_df['BNF NAME'].str.contains('Ampicillin', case=False)
combined_df.loc[amp_bool, 'parsed_drug_name'] = 'Ampicillin' # sets the row to amplicillin, if BNF NAME contains 'ampicillin.'

amox_bool = combined_df['BNF NAME'].str.contains('Amoxicillin', case=False)
combined_df.loc[amox_bool, 'parsed_drug_name'] = 'Amoxicillin'

co_amox_bool = combined_df['BNF NAME'].str.contains('Co-Amoxiclav', case=False)
combined_df.loc[co_amox_bool, 'parsed_drug_name'] = 'Co-Amoxiclav'

Наконец, выполните поворот данных и нанесите на график результаты:

combined_df.pivot_table(index='YEAR', columns='parsed_drug_name', values='ITEMS', aggfunc='sum').plot.bar(rot=0, stacked=True)

График стека

person DataSwede    schedule 27.11.2016
comment
Когда я пытаюсь это сделать, полученная гистограмма не складывается, т.е. она похожа на стандартную гистограмму только с одним лекарством (Ко-амоксиклав) ... какие-либо идеи относительно того, почему? - person Louise Stevens; 28.11.2016
comment
не уверен, связано ли это с добавлением .fillna (False)? - person Louise Stevens; 28.11.2016
comment
@LouiseStevens посмотрите на данные, которые вы пытаетесь построить. Присутствуют ли другие препараты? Вы можете посмотреть сводную таблицу, удалив .plot.bar(rot=0, stacked=True). - person DataSwede; 28.11.2016
comment
проблема в том, что эта строка кода неправильно выбирает все 3 препарата ... 'frame = frame [frame [' BNF NAME ']. str.contains (' Ampicillin 'and' Amoxicillin 'and' Co-Amoxiclav ')] 'пытается найти способ выбрать эти 3 струны. Я пробовал использовать "|" но это подходит только для двух аргументов ... - person Louise Stevens; 28.11.2016
comment
@LouiseStevens Три раздела, например: amp_bool = combined_df['BNF NAME'].str.contains('Ampicillin', case=False) и combined_df.loc[amp_bool, 'parsed_drug_name'] = 'Ampicillin', задают имя. Я сломал их, чтобы было легче. Написание одной строки регулярного выражения для извлечения всех трех одновременно вызывает у меня головную боль. Мой метод копировал и вставлял около 5 секунд. - person DataSwede; 29.11.2016