5 barplot через функцию (Python)
Занимаюсь анализом данных(только учусь), скачал датасет для тренировки, пытался обернуть в функцию построения графиков, вот так:
month_trend_2018 = month_trend.query('year == 2018').groupby('month').agg({'dead':'sum', 'injured':'sum', 'total':'sum'}).reset_index()
def bar_tables(data, x_col, y_col):
ax=data.plot(x=x_col, y=y_col, kind='bar', figsize=(25, 7), rot=360, grid=False)
for p in ax.patches:
height = p.get_height()
ax.text(p.get_x() + p.get_width() / 2,
height + 50,
'{:.0f}'.format(height),
fontsize = 13,
ha='center')
plt.legend(['Dead', 'Injured', 'Total'])
plt.title('Динамика по годам', size=16)
plt.xlabel('Год', size=14)
plt.ylabel('Жертвы, чел.', size=14)
plt.show()
bar_tables(month_trend_2018, month_trend_2018['month'], month_trend_2018[['dead', 'injured', 'total']])
Таблица выглядит так:
| month | dead | injured | total | |
|---|---|---|---|---|
| 0 | 1 | 23 | 89 | 112 |
| 1 | 2 | 43 | 64 | 107 |
| 2 | 3 | 15 | 68 | 83 |
В итоге ошибка:
KeyError Traceback (most recent call last)
c:\Users\pavel\Documents\Saves repository\saves\history_analysis.ipynb Ячейка 26 in <cell line: 1>()
----> 1 bar_tables(month_trend_2018, month_trend_2018['month'], month_trend_2018[['dead', 'injured', 'total']])c:\Users\pavel\Documents\Saves repository\saves\history_analysis.ipynb Ячейка 26 in bar_tables(data, x_col, y_col)
1 def bar_tables(data, x_col, y_col):
----> 2 ax=data.plot(x=x_col, y=y_col, kind='bar', figsize=(25, 7), rot=360, grid=False)
3 for p in ax.patches:
4 height = p.get_height()File ~\AppData\Roaming\Python\Python310\site-packages\pandas\plotting_core.py:937, in PlotAccessor.call(self, *args, **kwargs)
935 if is_integer(x) and not data.columns.holds_integer():
936 x = data_cols[x]
--> 937 elif not isinstance(data[x], ABCSeries):
938 raise ValueError("x must be a label or position")
939 data = data.set_index(x)File ~\AppData\Roaming\Python\Python310\site-packages\pandas\core\frame.py:3511, in DataFrame.getitem(self, key)
3509 if is_iterator(key):
3510 key = list(key)
-> 3511 indexer = self.columns._get_indexer_strict(key, "columns")[1]
3513 # take() does not accept boolean indexers
3514 if getattr(indexer, "dtype", None) == bool:File ~\AppData\Roaming\Python\Python310\site-packages\pandas\core\indexes\base.py:5782, in Index._get_indexer_strict(self, key, axis_name)
5779 else:
5780 keyarr, indexer, new_indexer = self._reindex_non_unique(keyarr)
-> 5782 self._raise_if_missing(keyarr, indexer, axis_name)
5784 keyarr = self.take(indexer)
5785 if isinstance(key, Index):
>5786 # GH 42790 - Preserve name from an IndexFile ~\AppData\Roaming\Python\Python310\site-packages\pandas\core\indexes\base.py:
5842, in Index._raise_if_missing(self, key, indexer, axis_name)
5840
if use_interval_msg:
5841 key = list(key)
-> 5842 raise KeyError(f"None of [{key}] are in the [{axis_name}]")
5844 not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())
5845 raise KeyError(f"{not_found} not in index")KeyError: "None of [Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype='int64')] are in the [columns]"
В таблице все колонки интовые, если это важно, то работаю в VSCode версия Python 3.10.4
Помогите пожалуйста разобраться с этим, в процессе гугления не смог найти описания подобных проблем.
Ответы (2 шт):
def bar_tables(data, x_col, y_col):
ax=data.plot(x=x_col, y=y_col, kind='bar', figsize=(25, 7), rot=360, grid=False)
...
bar_tables(month_trend_2018, month_trend_2018['month'], month_trend_2018[['dead', 'injured', 'total']])
Фактически вы делаете что-то такое:
df.plot(x=df['x'], y=df['y'])
А нужно указывать в качестве x и y названия колонок, а не сами данные:
df.plot(x='x', y='y')
Возвращаясь к вашему коду. Соответственно, нужно вызывать функцию, передавая не данные, а названия колонок. Насколько я понимаю, так:
bar_tables(month_trend_2018, 'month', ['dead', 'injured', 'total'])
Вообще, в пандас есть метод для гистограмм pandas.DataFrame.plot.bar, первая картинка совмещает все столбцы на одном рисунке, вторая делит картинку по столбцам:
import pandas as pd
import matplotlib.pyplot as plt
month = [1, 2, 3]
dead = [23, 4, 15]
injured = [89, 64, 68]
total = [112, 109, 83]
df = pd.DataFrame({'month': month, 'dead': dead, 'injured': injured, 'total': total})
ax = df.plot.bar(rot=0)
plt.show()
axes = df.plot.bar(rot=0, subplots=True)
axes[1].legend(loc=4)
plt.show()