Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unsupported operand type(s) for -: 'str' and 'float' when building a bar chart

Previously, I was asking to get week numbers on multiple year that is ready for plotting, and based on jezrael's answer I did this:

sheet2['device_create_week'] = sheet2['device_create_at'].dt.strftime('%Y-%V')
sheet2.groupby(['device_create_week']).size().reset_index(na‌​me='device created count weekly')

Then, I move to plotting

import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['figure.figsize'] = (10, 6)
rcParams['figure.dpi'] = 150
fig = plt.figure()
plt.bar(pre['user_create_week'],pre['user created count weekly'], align='center', alpha=0.5)
plt.xlabel('week')
plt.ylabel('frequency')
plt.show()
fig.savefig('test.jpg')

And then I see an error:

TypeError: unsupported operand type(s) for -: 'str' and 'float'

What am I supposed to do? I have the expected solution that can plot a bar chart with frequency weekly.

If you want data to try, here's my data you can try:

136     2014-08-27 10:19:46
245     2014-09-25 09:13:22
257     2014-09-29 15:22:16
258     2014-09-29 15:22:16
480     2015-02-02 10:01:25
481     2015-02-02 10:01:25
482     2015-02-02 10:01:25
483     2015-02-02 10:01:25
484     2015-02-02 10:01:25
485     2015-02-02 10:01:25
486     2015-02-02 10:01:25
487     2015-02-02 10:01:25
488     2015-02-02 10:01:25
536     2015-02-09 08:00:29
589     2015-02-02 10:01:25
590     2015-02-02 10:01:25
591     2015-02-02 10:01:25
592     2015-02-02 10:01:25
593     2015-02-02 10:01:25
594     2015-02-02 10:01:25
595     2015-02-02 10:01:25
596     2015-02-02 10:01:25
597     2015-02-02 10:01:25
694     2015-02-27 16:02:23
1573    2015-04-20 16:44:20
1574    2015-04-20 16:44:20
1779    2015-04-27 03:06:09
2119    2015-05-07 06:32:38
2120    2015-05-07 06:32:38
2306    2015-05-13 03:29:19
89876   2017-10-04 06:20:09
89933   2017-10-06 11:04:38
89943   2017-10-06 12:12:58
89947   2017-10-06 12:50:30
89952   2017-05-22 12:47:37
89957   2017-10-06 14:37:23
89958   2017-10-06 14:38:43
89984   2017-10-06 18:41:46
90022   2017-10-07 01:19:39
90053   2017-10-07 01:48:46
90117   2017-10-03 05:36:33
90122   2017-10-07 06:52:07
90129   2017-08-21 14:59:27
90145   2017-10-07 11:04:50
90157   2017-10-07 11:51:09
90164   2017-10-07 12:08:38
90202   2017-10-08 01:01:45
90216   2017-10-08 03:12:07
90222   2017-10-08 04:41:01
90228   2017-10-08 05:27:24
90238   2017-10-08 06:22:46
90250   2017-10-08 07:10:12
90266   2017-10-08 09:01:40
90276   2017-10-08 10:15:59
90291   2017-10-08 11:47:35
90294   2017-10-08 11:50:42
90298   2017-08-29 04:21:27
90313   2017-10-08 16:01:15
90363   2016-11-26 13:00:18
like image 683
Nabih Ibrahim Bawazir Avatar asked Dec 19 '22 03:12

Nabih Ibrahim Bawazir


2 Answers

Here is my answers based on your orignal code: use the plt.xticks() to make the str type work

Xweek_str=data1.device_create_week.tolist()
x = range(len(Xweek_str))

rcParams['figure.figsize'] = (10, 6)
rcParams['figure.dpi'] = 150
fig = plt.figure()
plt.bar(x,data1.device_created_count_weekly, align='center', alpha=0.5)
plt.xticks(x, Xweek_str)
plt.xlabel('week')
plt.ylabel('frequency')
plt.show()

So ,in your case, you just need to add :

Xweek_str=data1.device_create_week.tolist()
x = range(len(Xweek_str))

And plot like this:

plt.bar(x,data1['device created count weekly'], align='center', alpha=0.5)
plt.xticks(x, Xweek_str)

enter image description here

like image 109
ileadall42 Avatar answered Dec 20 '22 19:12

ileadall42


I think you can use instead:

plt.bar(pre['user_create_week'],pre['user created count weekly'], align='center', alpha=0.5)

DataFrame.plot.bar:

ax = pre.plot.bar(x='device_create_week', 
                  y='device created count weekly', 
                  align='center', 
                  alpha=0.5)

Also for save to picture need:

fig = ax.get_figure()
fig.savefig('test.jpg')

graph

If need append all possible combinations years + weeks need reindex:

import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['figure.figsize'] = (10, 6)
rcParams['figure.dpi'] = 150
fig = plt.figure()

sheet2['device_create_at'] = pd.to_datetime(sheet2['device_create_at'])
sheet2['device_create_week'] = sheet2['device_create_at'].dt.strftime('%Y-%V')
pre = sheet2.groupby(['device_create_week']).size()

a = sorted(['{}-{:02d}'.format(x, y) for y in range(1, 54) for x in range(2014, 2017)])
print (a[:10])
['2014-01', '2014-02', '2014-03', '2014-04', '2014-05', '2014-06',
 '2014-07', '2014-08', '2014-09', '2014-10']

pre = pre.reindex(a, fill_value=0)
print (pre.head())

ax = pre.plot.bar(align='center', alpha=0.5, width=1.0)

plt.xlabel('week')
plt.ylabel('frequency')
plt.show()

fig = ax.get_figure()
fig.savefig('test.jpg')

graph

Is possible omit some values in axis x :

spacing = 10
visible = ax.xaxis.get_ticklabels()[::spacing]
for label in ax.xaxis.get_ticklabels():
    if label not in visible:
        label.set_visible(False)

plt.show()

graph3

like image 26
jezrael Avatar answered Dec 20 '22 20:12

jezrael