- Pandas требует, чтобы столбцы имели одинаковую длину, поэтому
zip_longest
заполнит пробелы None
. - Существует несколько вариантов формирования данных в зависимости от того, как вы хотите их построить.
import pandas as pd
from itertools import zip_longest
import matplotlib.pyplot as plt
# data
d = {'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150.5', '150.5', '150.5'], 'word2': ['230', '230', '230', '230'], 'word3': ['542', '542', '540'], 'word4': ['134', '134']}
# since the values lists are uneven
cols = d.keys()
val = list(zip_longest(*d.values()))
# dataframe
df = pd.DataFrame(val, columns=cols, dtype=float)
word1 word2 word3 word4
0 122.0 230.0 542.0 134.0
1 121.2 230.0 542.0 134.0
2 132.0 230.0 540.0 NaN
3 132.0 230.0 NaN NaN
4 144.0 NaN NaN NaN
5 144.5 NaN NaN NaN
6 144.0 NaN NaN NaN
7 150.0 NaN NaN NaN
8 150.5 NaN NaN NaN
9 150.5 NaN NaN NaN
10 150.5 NaN NaN NaN
график с аннотациями
ax = df.plot.bar()
f = [df[c].value_counts().to_dict() for c in df.columns] # list of list of value counts
f = dict(kv for d in f for kv in d.items()) # this will break if the values for each word aren't unique
for p in ax.patches:
if p.get_height() > 0:
# add value at top of bar
ax.annotate(format(p.get_height(), '.1f'),
(p.get_x() + p.get_width() / 2., p.get_height() + 10),
ha = 'center', va = 'center', fontsize=9, rotation=90,
xytext = (0, 10), textcoords = 'offset points')
# add frequency of value at center of bar
ax.annotate(format(f[p.get_height()], '.0f'),
(p.get_x() + p.get_width() / 2., p.get_height() / 2),
ha = 'center', va = 'center', fontsize=9, rotation=0,
xytext = (0, 10), textcoords = 'offset points')
![enter image description here](https://i.stack.imgur.com/M520P.png)
tdf = df.T # transpose dataframe df
ax = tdf.plot.bar()
f = [df[c].value_counts().to_dict() for c in df.columns] # list of list of value counts
f = dict(kv for d in f for kv in d.items()) # this will break if the values for each word aren't unique
for p in ax.patches:
if p.get_height() > 0:
# add value at top of bar
ax.annotate(format(p.get_height(), '.1f'),
(p.get_x() + p.get_width() / 2., p.get_height() + 10),
ha = 'center', va = 'center', fontsize=9, rotation=90,
xytext = (0, 10), textcoords = 'offset points')
# add frequency of value at center of bar
ax.annotate(format(f[p.get_height()], '.0f'),
(p.get_x() + p.get_width() / 2., p.get_height() / 2),
ha = 'center', va = 'center', fontsize=9, rotation=0,
xytext = (0, 10), textcoords = 'offset points')
![enter image description here](https://i.stack.imgur.com/PjSO1.png)
Без аннотаций
- Раскрашивание
hue
помещает полосы смещены от центра на основе количества уникальных значений в столбце, используемых в этом случае hue
, word
. - В приведенном ниже примере все четыре слова содержат значение
150.5
, поэтому вы можете видеть их сгруппированными на графике.
- Полосы горизонтальны для размещения большое количество значений.
- Просто увеличьте
figsize
высоту.
import seaborn as sns
d = {'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150.5', '150.5', '150.5'], 'word2': ['230', '230', '230', '230', '150.5'], 'word3': ['542', '542', '540', '150.5'], 'word4': ['134', '134', '150.5']}
cols = d.keys()
val = list(zip_longest(*d.values()))
# dataframe
df = pd.DataFrame(val, columns=cols, dtype=float)
# convert from wide to long
df['id'] = df.index
dfl = pd.wide_to_long(df, stubnames='word', j='x', i='id').reset_index().rename(columns={'word': 'v', 'x': 'word'}).dropna()
# groupby for frequency counts
dflg = dfl.groupby('word').agg({'v': 'value_counts'}).rename(columns={'v': 'freq_count'}).reset_index().sort_values('v')
# plot
plt.figure(figsize=(6, 10))
p = sns.barplot(y='v', x='freq_count', data=dflg, hue='word', orient='h')
![enter image description here](https://i.stack.imgur.com/TXHfV.png)