import seaborn as sns import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline plt.rcParams['font.sans-serif']=['Microsoft YaHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号 from datetime import datetime plt.figure(figsize=(16,10)) import pyecharts.options as opts from pyecharts.charts import Line from pyecharts.faker import Faker from pyecharts.charts import Bar import os from pyecharts.options.global_options import ThemeType
读取整理好的数据:
alldfgbcountrysum=pd.read_csv("alldfgbcountrysum.csv",encoding='utf-8-sig')
将时间转换成datetime64[ns]
alldfgbcountrysum['Date']=pd.to_datetime(alldfgbcountrysum['Date']).dt.normalize()
绘制初始图像:
alldfgbcountrysum[['Confirmed','Date']].set_index(['Date']).plot(figsize=(20,12))
解决异常数据以及数据丢失的问题
allDate=alldfgbcountrysum.copy() allDate=allDate.groupby(['Date'])['Confirmed','Deaths','Recovered'].sum() #对每天所有的确诊人数,死亡人数,治愈人数进行汇总求和 allDate=allDate.reset_index().replace() allDate
数据当中日期的第一天:2020-2-24
数据当中日期的最后一天:2022-3-12
分析:
由于数据当中日期的第一天是:2020-2-24,从2020-2-25开始循环。24号是前一天,25号是当天,26号是后一天。
前一天确诊人数:bedata 当天确诊人数:data 后一天确诊人数:afdata
只要前一天的数据比当天的小,就说明是正常的,反之则异常,就进入循环。
异常数据当中的凸起部分:放大观察发现,异常数据是由两部分凸起组成,且第一小段的凸起大于第二小段。每小段凸起都是由一段数据构成的,在每小段凸起当中,数据仍然是增长的。
strftime()函数
:如果已经有了datetime对象,要把它格式化为字符串显示给用户,就需要转换为str,转换方法是通过strftime()实现。Timestamp
:时间戳,指1970年01月01日00时00分00秒起至现在的总秒数。datetime.timedelta
对象代表两个时间之间的时间差,两个date或datetime对象相减就可以返回一个timedelta
对象。如果有人问你昨天是几号,这个很容易就回答出来了。但是如果问你200天前是几号,则使用Python中datetime模块中的timedelta可以给出答案。datetime.date
: 表示日期的类datetime.date()
:来比较两个日期(天数),这样可以截断datetime,使其具有天数而不是小时的分辨率。drop
:使用drop删除表中的某一行或者某一列,它不改变原有的df中的数据,而是返回另一个dataframe来存放删除后的数据。
import datetime start=datetime.date(2020,2,25) last=datetime.date(2022,3,12) datalist=[] # 用来存放异常数据 for i in range((last-start).days+1): day=start+datetime.timedelta(days=i)# 类似一个计数器,随着循环不断增加天数。 # 前一天 bedata=allDate[allDate['Date']==pd.Timestamp(str(day+datetime.timedelta(days=-1)))]['Confirmed'].sum() # 当天 data=allDate[allDate['Date']==pd.Timestamp(str(day))]['Confirmed'].sum() # 后一天 # afdata=allDate[allDate['Date']==pd.Timestamp(str(day+datetime.timedelta(days=1)))]['Confirmed'].sum() # 判断数据是否异常 if(bedata>data):# 第一次进入这个条件判断是在第一个凸起与第二个凸起交界处,因为第二个凸起比第一个凸起小 if(bedata/2<data) & (bedata>data): # 凸出来的部分,向前找异常数据 j=-1 while allDate[allDate['Date']==pd.Timestamp(str(day+datetime.timedelta(days=j)))]['Confirmed'].sum()>data: # 此时前一天的数据大于当天的数据,进入while循环。循环的作用:找出从哪天开始,数据比当天的数据要小,则从那天开始数据就是正常的,而之间的数据就都是异常数据,把异常数据保存在datalist列表里面。 datalist.append(str(day+datetime.timedelta(days=j))) # 把异常数据变成字符串类型并且保持到列表 j-=1. else: #进入else说明这部分异常数据是下凹的数据,向后找异常数据 m=0 print(day+datetime.timedelta(days=-1))# 打印 while bedata>allDate[allDate['Date']==pd.Timestamp(str(day+datetime.timedelta(days=m)))]['Confirmed'].sum(): datalist.append(str(day+datetime.timedelta(days=m))) m+=1 print(datalist) allDate['Date']=allDate['Date'].apply(lambda x:x.strftime('%Y-%m-%d')) # 将Date中的数据都变成字符串类型 for i in allDate['Date']: if str(i) in datalist: print(i) allDate.drop(index=allDate[allDate['Date']==i].index[0],inplace=True) # 将原始数据当中包含有datalist元素的都删除
得到的结果(也就是找到的异常数据):
2021-12-14 ['2021-06-13', '2021-06-12', '2021-06-24', '2021-07-09', '2021-07-08', '2021-07-07', '2021-07-06', '2021-07-05', '2021-07-04', '2021-07-03', '2021-07-02', '2021-07-01', '2021-06-30', '2021-06-29', '2021-06-28', '2021-06-27', '2021-09-05', '2021-12-15', '2022-01-22', '2022-02-09', '2022-02-16', '2022-02-15', '2022-03-01', '2022-02-28', '2022-02-27', '2022-03-07', '2022-03-10'] 2021-06-12 2021-06-13 2021-06-24 2021-06-27 2021-06-28 2021-06-29 2021-06-30 2021-07-01 2021-07-02 2021-07-03 2021-07-04 2021-07-05 2021-07-06 2021-07-07 2021-07-08 2021-07-09 2021-09-05 2021-12-15 2022-01-22 2022-02-09 2022-02-15 2022-02-16 2022-02-27 2022-02-28 2022-03-01 2022-03-07 2022-03-10
allDate=allDate.sort_values(by='Date')
import os from pyecharts import options as opts from pyecharts.charts import Bar from pyecharts.options.global_options import ThemeType attrmax=allDate['Date'] v1=allDate['Confirmed'] bar=(Bar( init_opts=opts.InitOpts(bg_color='rgba(255,250,200,0.2)', width='1500px', height='800px', page_title='疫情数据', theme=ThemeType.ROMA ) ) .add_xaxis(attrmax.to_list()) .add_yaxis("人数",v1.to_list(),stack='stack1') .set_global_opts(title_opts=opts.TitleOpts(title="世界疫情数据"), xaxis_opts=opts.AxisOpts(name='日期',axislabel_opts={"rotate":50}), yaxis_opts=opts.AxisOpts(name='确诊人数:人')) .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) ) bar.render_notebook()