人生苦短,我用Python
话不多说,先看看数据。
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
os.chdir('C:/Users/花伦同学/Desktop/test/03/')#设置默认路径
data = pd.read_csv('知乎数据_201701utf8_2.csv',engine='python')#读取原始数据
data.head(10)#查看前10条数据
预览原数据
可以看到数据列表中,在“回答”、“提问”、“职业”等列中有NaN的空值,按照列的数据类型进行数据清洗,将空值替换为‘0’或者‘缺失数据’
创建数据清洗函数。
def data_cleaning(df):
cols = df.columns
for col in cols:
if df[col].dtype == 'object':
df[col].fillna('缺失数据', inplace = True)
else:
df[col].fillna(0, inplace = True)
return(df)
# 该函数可以将任意数据内空值替换
# 列为文字则返回‘缺失数据’否则列为数字返回‘0’
这个函数我们后面的文字中也会用到,适用面很广。
data0 = data_cleaning(data)
data0.head(10)
清洗后数据
数据清洗完成后,就可以进行数据分析了,这次主要从两个维度进行分析:
1.知友的全国分布情况。(主要是知友数量和知友的密度)
2.各个高校知友的关注和被关注情况。
第一个纬度分析。
data_city_num = data0.groupby('居住地').count()#按地域分组
data_city_num['知友数量'] = data_city_num["_id"]#得到知友各城市的数量
data_pop = pd.read_csv('六普常住人口数.csv', engine = 'python')#读取人口数据
#print(data_city_num.head(10))
data_pop['城市'] = data_pop['地区'].str[:-1]#建立新标签,去掉"市"
data_md = pd.merge(data_city_num, data_pop, left_index = True, right_on = '城市', how = 'inner')[['知友数量','城市','常住人口']]
#合并列表,为了下一步计算密度
data_md['知友密度'] = data_md['知友数量']/data_md['常住人口']#计算密度
#data_md.head(10)
为了方便比对,数量和密度之间的相对情况,这里创建一个标准化的函数对数据进行标准化。
def standard(df,*cols):
colnames = []
for col in cols:
colname = col + '_std'
df[colname] = (df[col] - df[col].min())/(df[col].max()-df[col].min())*100
colnames.append(colname)
return(df,colnames)
#标准化数据,返回dataframe和列名,返回类型为元祖
data_md_std = standard(data_md,'知友密度','知友数量')[0]#获取返回的dataframe
data_colnames = standard(data_md,'知友密度','知友数量')[1]#获取返回的列名
data_md_std.head()
#data_colnames
data_top20_md = data_md_std.sort_values('知友密度_std',ascending = False)[['城市','知友密度_std']].iloc[:20]
data_top20_sl = data_md_std.sort_values('知友数量_std',ascending = False)[['城市','知友数量_std']].iloc[:20]
#提取数量和密度的前20行数据,及top20
#print(data_top20_sl,data_top20_md)
然后制作图表,更直观的查看数据。
fig1 = plt.figure(num=1,figsize=(12,4))
y1 = data_top20_sl['知友数量_std']
plt.bar(range(20),
y1,
width = 1,
facecolor = 'yellowgreen',
edgecolor = 'k',
tick_label = data_top20_sl['城市'])
plt.title('知友数量TOP20\n')
plt.grid(True, linestyle = '--', color = 'grey', axis = 'y')
for i, j in zip(range(20),y1):
plt.text(i-0.5,2,'%.1f' %j, color = 'k', fontsize = 12)#用循环给图加标注
fig2 = plt.figure(num=2,figsize = (12,4))
y2 = data_top20_md['知友密度_std']
plt.bar(range(20),
y2,
width = 1,
facecolor = 'lightblue',
edgecolor = 'k',
tick_label = data_top20_md['城市'])
plt.title('知友密度TOP20\n')
for i, j in zip(range(20),y2):
plt.text(i-0.5,2,'%.1f' %j, color = 'k',fontsize = 12)#用循环给图加标注
知友数量TOP20
知友密度TOP20
第二个纬度分析
根据关注者和被关注的情况进行分组
data_gz = data0.groupby('教育经历').sum()[['关注','关注者']]
#data_gz.head(20)
data_top20_fans = data_gz.sort_values('关注者',ascending = False).drop(['缺失数据','医学','我的老師,是山川和大地','重庆第一工程尸培养基地',
'五道口男子职业技术学院','为往圣继绝学','本科'])[:20]
#查看数据后发现教育经历有很多乱填的,这里要把这些信息去掉(┑( ̄Д  ̄)┍)
data_top20_fans
关注人数高校top20
然后做数据的可视化,结果就一目了然了。
plt.figure(figsize = (16,10))
x = data_top20_fans['关注']
y = data_top20_fans['关注者']
x_mean = data_top20_fans['关注'].mean()
y_mean = data_top20_fans['关注者'].mean()
plt.scatter(x,y,marker='.',
s = y/1000,
cmap = 'Blues',
c = x,
label = '学校')
plt.axvline(x_mean,label="平均关注人数:%i人" % x_mean,color='r',linestyle="--",alpha=0.8) # 添加x轴参考线
plt.axhline(y_mean,label="平均粉丝数:%i人" % y_mean,color='g',linestyle="--",alpha=0.8) # 添加y轴参考线
plt.legend(loc = 'upper left')
plt.grid()
for i,j,k in zip(x,y,data_top20_fans.index):
plt.text(i+500,j+500,k)
关注人数高校top20
我们可以清楚的看到浙江大学在关注人数和被关注人数都是遥遥领先,其次是北京大学。北京电影学院的粉丝数量较多但关注的人数较少...
这里还介绍一种数据可视化的方法bokeh,大家可以参考这个代码试试。
from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource
from bokeh.models import HoverTool
df2 = data_top20_fans.copy()
df2.columns = ['gz','gzz']
df2.index.name = 'xx'
df2['size'] = df2['gzz'] / 20000
source = ColumnDataSource(df2)
hover = HoverTool(tooltips = [
('学校','@xx'),
('关注人数','@gz'),
('被关注人数','@gzz')
])
p = figure(plot_width = 800,plot_height = 600,title = 'top20',tools=[hover,'box_select,reset,wheel_zoom,pan,crosshair'])
p.circle(x = 'gz',y = 'gzz',source = source,size = 'size',fill_color = 'blue',fill_alpha = 0.6)
show(p)
网友评论