Seaborn实战:签证数据可视化

学的时候顺便想拿点东西练练手,顺便也可以看看seaborn到底有什么用处。正好Checkee.info上面有足够多的签证数据,就扒拉下来看看。

取数据,洗数据

checkee.info上的数据格式其实非常友好。高手直接爬虫就能很方便的爬下来。可是我还不会,就直接一口气复制下来。

  • 新建一个csv文档,前面的update和后面的details可以很方便的用查找替换直接删去。
  • 初步处理好文件之后先保存。准备写代码。
import numpy as np
import pandas as pd
from scipy import stats, integrate
import matplotlib.pyplot as plt
checker = pd.read_csv('fullchecklist.csv',sep = '   ') #读取csv
del checker['ID'] 
del checker['Major']
checker.to_csv('fullchecklist_filter.csv',index = None) #保存csv
  • 先用pandas库对csv进行读取。使用pd.read_csv这个函数。因为我们复制下来的分隔符是“ ”而csv数据间默认的分隔符是英文逗号。所以需要声明sep = ' '。
  • 第二三步 del checker['ID']、del checker['Major'],即将数据中名为“ID”和“Major”列删除。用不上ID所以删了。对于Major,因为checkee上没有提供标准的专业选择,所以不少相同专业的人填入的内容可能也不太一样。而且有人还输入了各种符号,给我们后来的操作造成障碍,所以删了。
  • 最后用to_csv函数保存新的csv文件,顺便传入index = None,不然输出的csv文件中会增加一列用来计数。注意,保存后的csv文件里已经将分隔符换为了标准的英文逗号。

到这里,粗糙的处理就已经完成了。其实已经可以开始绘图了,但是还有一些小地方可以做的更好。

  • 第一,注意到US Consulate(即面签使馆)列不仅包括了国内的使馆,也有国外的使馆。在分使馆绘图时会造成项目过杂的情况。这里我们通过一个正则替换将所有非国内使馆替换为“Overseas”
import pandas as pd
import re #导入正则库
try:
    datas = open('fullchecklist_filter.csv','r')
    #读取文件
    ss = open('newchekee.txt','w') 
    #以写入方式打开一个新的txt文件
    l = 1
    while True: #读取文件循环
        line = datas.readline() 
        if l == 1:  #第一行,因为这行是表头
            ss.write(line)
            l += 1
            continue #继续下一个循环
        if line: #如果读取成功
            l += 1
            m = re.match(r'([A-Z][0-9],[0-9a-zA-Z]+,)([0-9a-zA-Z]+)([0-9a-zA-Z &,-.]+)',line)
            #正则读取
        if m:
               plcstr = str(m.group(2))
                 #按照正则规则读取的第二组字符串,即US Consulate
               if plcstr == 'BeiJing'or plcstr == 'ShangHai'or plcstr == 'GuangZhou'or plcstr == 'ShenYang'or plcstr == 'ChengDu'or plcstr == 'HongKong': 
                #若是国内的,直接原样写入
                    ss.write(m.group(0))
                    ss.write('\n')
               else:
                #若是国外的,将第二组替换为Overseas再写入
                    ss.write(m.group(1))
                    ss.write('Overseas')
                    ss.write(m.group(3))
                    ss.write('\n')
        else:
            break
finally: #关闭文件
    if datas:
        datas.close()
    if ss:
        ss.close()
  • 第二,注意到时间为YYYY-MM-DD格式,直接将所有的“-”替换为“,”。在表头添加一下就行:
Check_Year, Check_Month, Check_Day, Complete_Year, Complete_Month, Complete_Day,

这样就能保证表头的数目和数据数目一致了。之后也可以用前面的del语句删除无用的列。

del checker['Check_Year']
del checker['Complete_Year']
del checker['Complete_Month']
del checker['Complete_Day']

到这里,数据就处理完成了。

开始画图

导入各种库

import numpy as np
import pandas as pd
from scipy import stats, integrate
import matplotlib.pyplot as plt
from matplotlib import gridspec
import re
import seaborn as sns

然后读取csv文件,并生成一些我们需要的子表。这里使用了pandas的.query语句。随后我们将checker的info打印出来看看分别都是些什么东西:

checker = pd.read_csv('checkeefil2.csv')
F1 = checker.query("Visa_Type == 'F1'")
#将checker里Visa_Type为F1的数据行取出
J1 = checker.query("Visa_Type == 'J1'")
Clear_Case = checker.query("Status == 'Clear'")
FJ1 = pd.concat([F1,J1])
#将表F1和J1合并

打印一下

checker.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3762 entries, 0 to 3761
Data columns (total 7 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
0   Visa_Type     3762 non-null   object
1   Visa_Entry    3762 non-null   object
2   US_Consulate  3762 non-null   object
3   Status        3762 non-null   object
4   Check_Month   3762 non-null   int64  
5   Check_Day     3762 non-null   int64  
6   Waiting Days  3762 non-null   float64
dtypes: float64(1), int64(2), object(4)

其实剩下的东西也不多了。就用这些东西来做可视化吧。

  • 首先定好画布大小和分栏,这里我们决定画2个图。
sns.set(font='Helvetica',font_scale=1) #使用seaborn风格,字体设置为Helvetica,默认缩放  
plt.figure(figsize=(12,8)) #画布大小1200*800
gs = gridspec.GridSpec(1, 2, width_ratios=[2, 1])#定义2x2个子图,宽度比为2:1。使位于左边的图更宽一些。
cmap = sns.cubehelix_palette(3,start = .8, rot = -1.2, light = .6)#定义一个好看的配色方案

# Figure 1
ax0 = plt.subplot(gs[0])
sns.stripplot(x="US_Consulate", y="Waiting Days",hue="Status",
order=['BeiJing','ShangHai','GuangZhou','ShenYang','ChengDu','HongKong','Overseas'],
data=checker,palette=cmap,jitter=.35,dodge=True,size=3,alpha=.8,ax=ax0)

ax0.set_xlabel('Consulate Location',fontsize=12)
ax0.set_ylabel('Waiting Days',fontsize=15)
plt.legend(loc=1,fontsize=10)
ax0.tick_params(axis='y',labelsize=13)
ax0.tick_params(axis='x',labelsize=10)
plt.ylim(-60, 480)

# Figure 2
ax1 = plt.subplot(gs[1])
sns.stripplot(x="Status", y="Waiting Days",hue="Visa_Type",
order= ['Pending','Clear','Reject'],
data=FJ1,palette=cmap,
#jitter=.2,
dodge=True,size=2.5,alpha=.8,ax=ax1)
plt.legend(loc=1,fontsize=10)
plt.ylim(-60, 480)
ax1.set_xlabel('F1 & J1 Visa Cases',fontsize=12)
ax1.set_ylabel('Waiting Days',fontsize=15)
ax1.tick_params(axis='y',labelsize=13)
ax1.tick_params(axis='x',labelsize=10)

参考

  • Pandas库数据操作:

Pandas中文网

  • Seaborn的画图类型,参数调整和色彩搭配:

Seaborn常见绘图总结

Seaborn 调色盘color_palette()

Seaborn官网

  • 签证数据:

Checkee - Check Reporter

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。