数据分析案例练习——中国姓氏排行研究

1,265 阅读5分钟

目的和背景

目的

对中国姓氏数据进行处理,查看姓氏“普遍指数”和奔波指数

数据背景

三张数据表,两张个人信息表(数据量总和263w+),一张中国行政代码对照表(数据量3500+)

数据预处理

数据读取

os.chdir('G:\数据分析资料*******')
#读取数据:
df1=pd.read_csv('data01.csv',encoding='utf-8')
df2=pd.read_csv('data02.csv',encoding='utf-8')
df3=pd.read_excel('中国行政代码对照表.xlsx',sheet_name =0,encoding='utf-8')

数据表连接与合并

#数据表连接,结合“户籍地城市编号”及“中国城市代码对照表”数据,将城市经纬度连接进数据中
def data_combine(df_data01,df_data02,df_code):
    #df_data01,df_data02为两张个人信息表,df_code为城市代码对照表
    df_con=pd.concat([df_data01,df_data02])#合并成一个数据表
    df_code['行政编码']=pd.to_numeric(df_code['行政编码'],errors='coerce')
    df_con['户籍地城市编号']=pd.to_numeric(df_con['户籍地城市编号'],errors='coerce')
    df_code['行政编码']=pd.to_numeric(df_code['行政编码'],errors='coerce')  
    data_01=pd.merge(df_con,df_code,left_on='户籍地城市编号',right_on='行政编码')
    print('merge前的数据为:',len(df_con),'\n,merge后的数据为:',len(data_01))
    del data_01['户籍地城市编号']
    del data_01['行政编码']
    data_01['工作地']=data_01['工作地'].str[:15]
    return(data_01)
data_01=data_combine(df1,df2,df3)

这里值得一提的是数据表merge合并的时候需要统一转换数据类型和考虑数据有效性。我开始直接合并,报错,我试着用pd.astype()函数直接都转换为字符型,合并后发现260w+的数据少了接近200w数据。然后使用了pandas.to_numeric(arg,errors ='raise',downcast = None )函数转换数据才使得合并后的数据量正常。

提取工作地的省、市、县(区)以及未识别值处理

def get_provinces(df):#提取省
    df['工作地_省']=df['工作地'].str.split('省').str[0]
    return(df)
data_01=get_provinces(data_01)
def get_city(df):#提取市
    df['工作地_市'] = df['工作地'].str.split('省').str[1].str.split('市').str[0]
    df['工作地_市'][df['工作地_省'].str.len() > 5] = df['工作地_省'].str.split('市').str[0]
    return(df)
data_02=get_city(data_01)
def get_county(df):#提取区县
    df['工作地_区县']=''
    df['工作地_区县'][(df['工作地_市'].str.len() < 5)&(df['工作地'].str.contains('区'))] = df['工作地'].str.split('市').str[1].str.split('区').str[0] + '区'  
    df['工作地_区县'][(df['工作地_市'].str.len() > 5)&(df['工作地'].str.contains('区'))] = df['工作地'].str.split('区').str[0] + '区'
    df['工作地_区县'][(df['工作地_市'].str.len() < 5)&(df['工作地'].str.contains('县'))] = df['工作地'].str.split('市').str[1].str.split('县').str[0] + '县'  
    df['工作地_区县'][(df['工作地_市'].str.len() > 5)&(df['工作地'].str.contains('县'))] = df['工作地'].str.split('县').str[0] + '县'
    return(df)
data_03=get_county(data_02)
def get_else(df):#整理未识别工作地
    df['工作地_省'][df['工作地_省'].str.len() > 5] = '未识别'
    df['工作地_市'][df['工作地_市'].str.len() > 5] = '未识别'
    df['工作地_区县'][(df['工作地_区县'].str.len() > 5) | (df['工作地_区县'].str.len() < 2)] = '未识别'
    return(df)
data_04=get_else(data_03)
data_04.columns = ['姓', '工作地', '户籍所在地_省', '户籍所在地_市','户籍所在地_区县', '户籍所在地_lng', '户籍所在地_lat', '工作地_省','工作地_市','工作地_区县' ]
#调整数据列顺序

数据可视化

二维统计

这块使用bokeh做可视化

import matplotlib.pyplot as plt
from bokeh.plotting import figure,show,output_file
from bokeh.models import ColumnDataSource,HoverTool
from bokeh.layouts import gridplot
#(1)数将数据按照“姓”做统计,找到数量最多的TOP20
name_count=data_04['姓'].value_counts()[:20]
result_01=pd.DataFrame({
    'count':name_count,
    'count_per':name_count/name_count.sum()
})
name_list=result_01.index.tolist()
source=ColumnDataSource(result_01)
output_file('name_rank.html')

#姓氏top20计数图
hover1 = HoverTool(tooltips = [('姓氏计数', "@count")])
result1=figure(plot_width = 800, plot_height = 250, x_range = name_list,
                 title = '中国姓氏TOP20 - 计数',
                 tools = [hover1, 'reset, xwheel_zoom, pan'])
result1.vbar(x='index', top='count', source=source,width=0.9, alpha = 0.8,color = 'lightseagreen') 
result1.ygrid.grid_line_dash = [6, 4]
result1.xgrid.grid_line_dash = [6, 4]

#姓氏top20占比图
hover2=HoverTool(tooltips=[('姓氏占比',"@count_per")])
result2=figure(plot_width = 800, plot_height = 250, x_range = name_list,
                 title = '中国姓氏TOP20 - 占比',
                 tools = [hover2, 'reset, xwheel_zoom, pan'])
result2.vbar(x='index', top='count_per', source=source,width=0.9, alpha = 0.8,color = 'deeppink') 
result2.ygrid.grid_line_dash = [6, 4]
result2.xgrid.grid_line_dash = [6, 4]

p = gridplot([result1], [result2])
show(p)

可视化图形如下

可以看出,中国姓氏前三甲为‘王’,‘张’,‘李’,其次是‘刘’姓、‘陈’姓、‘杨’姓,后面的‘吴赵周徐黄孙’姓数量都比较接近(数据仅供训练,没有任何实际意义)

人群地理位置分布可视化

这里选择查看老王家的姓氏全国分布,先获取老王的数据,并读取到本地‘.xlsx’文件中

data_wang=data_04[data_04['姓']=='王']
write_file=pd.ExcelWriter('G:\数据分析资料\数据分析师群资料\【非常重要】项目资料\项目09中国姓氏排行研究(更新地图shp)\项目09中国姓氏排行研究\wangb1.xlsx')
data_wang.to_excel(write_file,'sheet1',index=False)
write_file.save()

打开文件,这里使用Excel的powermap制作,

打开3D地图

3D人口柱状图

打开powermap后,选择平面地图——>点的经度、维度——>主题环境

制作人口柱状图如下: 以姓的数量作为柱状图的高度

人口热力图

echarts制图

生成echarts制图需要的数据

data_wang2=data_wang.groupby(['户籍所在地_lng', '户籍所在地_lat', '户籍所在地_市'])['姓'].count()
data_wang2 = data_wang2.reset_index()
data_wang2.columns = ['lng', 'lat', 'name', 'value'] 
writer=pd.ExcelWriter('G:\数据分析资料\数据分析师群资料\【非常重要】项目资料\项目09中国姓氏排行研究(更新地图shp)\项目09中国姓氏排行研究\wangb2.xlsx')
data_wang2.to_excel(writer,'sheet1',index=False)
writer.save()

将‘wangb2.xlsx’替换到‘data.xlsx’文件中

将数据转换为方便echarts读取的json格式

import pandas as pd
import os
os.chdir('G:\数据分析资料******\ch0403_空间柱状图\data02_3D_Bar_Map')  # 输入文件所在路径,'
data = pd.read_excel('data.xlsx', sheetname=0,header=0)
datajs = data.to_json(orient='records',force_ascii=False)
print('转换后数据为:\n',datajs)

然后将此数据复制echarts的data中

生图如下

图形上的点都比较小,而且分布需要调整

打开坐标拾取器,选取中部地区武汉的经纬度,做地图中心点

调整地图的中心点坐标,视角远近,点柱大小

最后,echarts制作的3D柱状图如下

可以看出老王在全国均有分布,东部地区偏多,其次是中部地区(未完待续)