以下是数据清单,需要从本地这份数据清单中获取我们需要的这三列信息。
导包,这些包都需要用到:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import codecs
import csv
import datetime as dt
import pandas as pd
from pandas import DataFrame
#1、加载外部的csv数据:民调结束的时间、希拉里的民调数据、特朗普民调数据
#获取三列需要的数据
data = np.loadtxt('./presidential_polls.csv',dtype=np.str,usecols=(7,17,18),delimiter=',')
#print(data)
#获取除去标题的纯数据列
data_adjpoll = data.tolist()[1:]
#将日期数据进行处理 mm/dd/yyyy -> yyyy-mm
date = [i[0] for i in data_adjpoll] #list型
dates=[dt.datetime.strptime(date,'%m/%d/%Y') for date in date] #list型
date_new = [i.strftime('%Y-%m') for i in dates]#date_new是转换好格式以后的日期list
#先把两个候选人的数据提取出来(有空值,把空值置0)
#得到两组浮点类型数据,方便计算求和
adjpoll_clinton = [i[1] for i in data_adjpoll]
for i in range(len(adjpoll_clinton)):
if adjpoll_clinton[i] =='':
adjpoll_clinton[i]='0'
adjpoll_clinton_arr = np.array(adjpoll_clinton,dtype=np.float64)
adjpoll_trump = [i[2] for i in data_adjpoll]
for i in range(len(adjpoll_trump)):
if adjpoll_trump[i] =='':
adjpoll_trump[i]='0'
adjpoll_trump_arr = np.array(adjpoll_trump,dtype=np.float64)
#使用dataframe新建一个全新的二维数组,求和
my_data = pd.DataFrame({'Date':date_new, 'adjpoll_clinton_arr': adjpoll_clinton_arr, 'adjpoll_trump_arr':adjpoll_trump_arr},
columns=['Date','adjpoll_clinton_arr','adjpoll_trump_arr'])
sum_data_clinton = my_data['adjpoll_clinton_arr'].groupby(my_data['Date']).sum()
print('希拉里每个月的民调数据和如下:')
print(sum_data_clinton)
sum_data_trump = my_data['adjpoll_trump_arr'].groupby(my_data['Date']).sum()
print('特朗普每个月的民调数据和如下:')
print(sum_data_trump)
得到的川普竞选数据:
#获取民调数据,求和
print('希拉里民调数据总和为:',adjpoll_clinton_arr.sum())
print('--------------------------------')
print('川建国民调数据总和为:',adjpoll_trump_arr.sum())
#折线图反映两位候选人民调的走势
ax = plt.subplot()
ax.set_xlabel('月份')
ax.set_ylabel('当月民调数据和')
ax.set_title('两位候选人民调的走势')
months = ['15-11','15-12','16-1','16-2','16-3','16-4','16-5','16-6','16-7','16-8','16-9','16-10']
data = [[1916,1937],[4637,4088],[6585,6253],[7946,7672],[11156,9991],[11579,9884],[12242,12069],[19771,18154],
[23233,22757],[67909,66428],[102445,106065],[165319,164990]]
data_clinton=[i[0] for i in data]
data_trump=[i[1] for i in data]
print('克林顿每月去小数点后数据:',data_clinton)
print('川普每月去小数点后数据:',data_trump)
plt.plot(months,data_clinton,'b',alpha=0.5,label='Trump')
plt.plot(months,data_trump,'r',alpha=0.5,label='Clinton')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.xticks(rotation=30)
plt.grid(linestyle='--') # 设置背景网格(虚线)
plt.legend(loc='best') # 自动在最合适的位置
plt.show()
#柱形图比较两位候选人民调的数据
ax = plt.subplot()
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = np.arange(12)
months = ['15-11','15-12','16-1','16-2','16-3','16-4','16-5','16-6','16-7','16-8','16-9','16-10']
data_cliton = [1916,4637,6585,7946,11156,11579,12242,19771,23233,67909,102445,165319]
data_trump = [1937,4088,6253,7672,9991,9884,12069,18154,22757,66428,106065,164990]
bar_width = 0.2
#创建柱状图 x横轴,y纵轴,bar宽度,描边线透明
bars=plt.bar(x, data_cliton,width=bar_width,label='Clinton',color='#2874A6')
bars=plt.bar(x+bar_width, data_trump,width=bar_width,label='Trump',color='#2ECC71')
plt.legend(loc='best')
plt.grid(linestyle='--')
ax.set_ylabel('当月民调数据和')
ax.set_xlabel('月份')
#设置y轴的范围
ax.set_ylim(0,170000)
plt.xticks(x+bar_width/2,months)
ax.set_title('两位候选人民调的走势')
plt.show()
任务是处理2016年两位美国总统竞选人每个月的票选数据并绘制相关折线图、柱状图。
需要对数据格式敏感,比如str类型、int类型、float类型之间的转换。日期格式通过导入datetime模块更改日期格式,完成数据统计。另外,在表格中数据出现异常时要及时做差错处理。有两种办法:一是用抛出异常try-except:pass把空数据抛出;二是用len()函数对数据求长度,若长度为0则赋值为0,也可以解决问题。
很多东西,都要自己动手做了才知道辛苦。像平时这种级别的项目老师带着做只会嫌太简单了。可真正完全交付到自己手里才知道原来代码的修修补补是这么的麻烦、费时费力。
希望以后能加强自己动手能力,从原理上清楚代码逻辑,这样一个稍微有点规格的项目交到你手里,起码有个思路,而不是像个愣头青一头雾水只能干巴巴的坐着,盯着屏幕发呆,多捞啊。
—— ——Seina 2020/7/20
一些不起眼的碎碎念:
啊,还是有好多没完善的地方啊。
首先我竟然妄想把整个文档的数据抓取出来,但是数组不可能储存这么大的数据量…所以使用了usecols=(7,17,18) 把特定的三列数据提取出来构成一个二维数组。
日期转换格式也是伤透了脑筋,主要是数据类型不符合导致转换不成功。从二维数组提取出来的日期既不是str也不是int,只能借助datetime按格式强制转换成str,在str转str改变日期格式。得到data_new为转换好格式的数组。
其实整个项目完全可以不使用pandas,单纯靠numpy和matplotlib完成。但是我实在没搞出怎么把转换好的日期格式那一列数据写进原来的二维数组中。最后我突发奇想,干脆用pandas下面的Dataframe模块新建一个数组好了。
问题又又来了,dataframe新建好的数组确实显示很正确,但是用sum()求和函数发现完全不能求和!因为数据都是int型啊,sum()函数只会把这些数字拼接在一起,不会计算。得了,只能先循环遍历强制转换数据为float64型。
问题又又又来了。转换数据时总是报错。一查数据发现竟然有空值…我想啊想啊,实在没办法,就写一个循环语句,先判断数据的长度len(),如果len为0当然是一个空数据,我赋值给他为0。这样才避免数据转换类型报错。
这些工作做完,总算按月份求和,按年求和就没有什么问题了。。。
后面的画曲线图就好做的,照着模板做就好。
但是。。。做柱状图的时候又来问题了。我想做两根柱子放在一起,这样数据才方便比较。老师也没教,怎么写?上网查呗。。。找了好几个模板,一个一个慢慢试,终于成功了。关键在于
令x = np.arange(12)代表x轴12个月份。接下来调用plt.xticks(x+bar_width/2,months)可以实现功能。