Reputation: 806
I have some problems to plot the following values:
my_dict={'word1': ['31', '131', '2'], 'word2': ['42', '33', '154', '21']}
What I have done is
plt.bar(my_dict.keys(), my_dict.values(), color='g')
but I got this error:
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('
Then I have tried with
plt.plot(*zip(*sorted(my_dict.items())))
plt.show()
but I got this other error:
TypeError: unhashable type: 'list'
I would be interested in frequency.
What should I do to fix it?
From the original dataset (as I have got some error to replicate the code):
my_dict = defaultdict(list)
print({ k : v for k, v in my_dict.items() })
output:
{'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']}
I would need to plot the frequency of values in each word (for example, for word1 I should have a frequency of 2 for 132 and 144, then 3 for 150.5, 1 for all the other values).
Upvotes: 1
Views: 4174
Reputation: 62393
pandas
and zip_longest
zip_longest
will fill blanks with 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')
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')
hue
places the bars off-center based upon the number of unique values in the column used by hue
, word
in this case.
150.5
, so you can see them grouped in the plot.figsize
height.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')
Upvotes: 1
Reputation: 27557
matplotlib
:import matplotlib.pyplot as plt
from numpy import random
mydict={'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']}
for k,l in mydict.items():
labeled = False
c=random.rand(3,)
for v in l:
if labeled:
plt.bar(v,len([d for d in l if d==v]),color=c)
else:
plt.bar(v,len([d for d in l if d==v]),label=k,color=c)
labeled = True
plt.legend()
plt.show()
Upvotes: 2