2021-1-数据分析-Task1-论文数据统计

统计2019年后计算机各个方向论文数量

步骤拆解

  1. 数据导入
  2. 数据预处理——类别信息拆分、保留19年之后数据
  3. 获取论文类别信息(爬虫)
  4. 统计计算机方向论文
  5. 可视化

1.数据导入

1.1.导入包

# 导入所需的包
import seaborn as sns # 导入画图的包
from bs4 import BeautifulSoup # 导入网页抓取包
import re # 用于正则表达式,匹配字符串
import requests #用于网络连接,发送网络请求,使用域名获取对应信息
import json #读取数据,我们的数据为json格式的(处理网络爬虫数据的常用格式)
import pandas as pd #数据处理、数据分析库
import matplotlib.pyplot as plt #画图工具

1.2 导入数据

# 读入数据
data=[] #初始化 # 使用with语句优势:1.自动关闭文件句柄;2.自动显示(处理)文件读取数据异常
with open("arxiv-metadata-oai-snapshot.json",'r') as f:
    for line in f:
        data.append(json.loads(line))
    
data=pd.DataFrame(data) # 将list变为dataframe格式,方便使用pandas进行分析
data.shape #显示数据大小

处理前的数据有179w,14行参数
1.3 查看数据基本信息

data.head()

在这里插入图片描述

data.info()

在这里插入图片描述

2.数据预处理

2.1 拆分类别字段

# 简单看下类别数据
data["categories"].describe()
# 一共有1796811样本,不同的值由62055种(A+B 和 A+C是不同的两种)
# 出现频率最高的是 astro-ph,频次是86914

# 由于论文的类别不止一种,因此需要将categories字段拆开,分别统计每个类别的数量
unique_categories=set([i for l in [x.split(' ') for x in data["categories"]] for i in l])
# set函数:set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据  ——set()是一种创建集合的标准方法
# x.split(' ')表示以空格为分界对数据进行拆分

unique_categories 
# 是一个集合

在这里插入图片描述
通过计算unique_categories这个集合的项目数得到一共有多少种相互独立的论文类别

len(unique_categories)
# 一共176种不同的论文类型
# len() 方法,用于返回列表、元组的项目数或长度

在这里插入图片描述
2.2 仅保留2019年以后的数据(被统计的对象)

  • 原来表示时间的update_date字段为object类型,需转换成datetime类数据,从而从中提取出年份数据
# 对时间特征进行处理,只看2019年以后的数据
# 时间数据的字段是update_date
# 简单观察下发现是objetc类的数据,应该要转成datetime类?
data["update_date"].head()

data["year"]=pd.to_datetime(data["update_date"]).dt.year 
#pd.to_datetime 转为datetime格式数据
# .dt.year 仅保留年份

data["year"].head()
#转换为年份完毕

在这里插入图片描述

#找出时间在2019年以后(含)的所有行
data1=data[data["year"]>=2019]

data1.head(5)

2.3 简单聚合下不同年份、不同类型下的论文数
groupby
被聚合对象.groupby[‘以x字段聚合’,‘以y字段聚合’].统计方式
e.g.

grouped=data1.groupby(['categories','year'])
# 以 categories 进行排序,如果同一个categories 相同则使用 year 特征进行排序
grouped.count()
# 不同类型论文在2019年后不同年度的分布

在这里插入图片描述

3.获取论文类别的关联关系

用于锁定哪些论文类型属于计算机类

3.1 爬取论文类型计算关系

re.sub(pattern, repl, string, count=0, flags=0)

关于正则:

  • pattern : 正则中的模式字符串
  • repl : 替换的字符串,也可为一个函数
  • string : 要被查找替换的原始字符串
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
  • flags : 编译时用的匹配模式,数字形式
  • 其中pattern、repl、string为必选参数 ‘’’
# 爬取所有类别
website_url=requests.get('https://arxiv.org/category_taxonomy').text #获取网页的文本数据
soup= BeautifulSoup(website_url,'lxml') #爬取数据,这里使用lxml的解析器,加速
root=soup.find('div',{'id':'category_taxonomy_list'})  #找出 BeautifulSoup 对应的标签入口
tags=root.find_all(["h2","h3","h4","p"], recursive=True) # 读取 tags
# 将网页转为源代码格式,大体能看懂是一个找要爬取位置的操作

# 初始化str和list变量
# 从源代码中大致看出分三个层级
level_1_name=""
level_2_name=""
level_2_code=""
level_1_names=[]
level_2_codes=[]
level_2_names=[]
level_3_codes=[]
level_3_names=[]
level_3_notes=[]

# 进行抓取的过程
for t in tags:
    if t.name=="h2":
        level_1_name=t.text
        level_2_code=t.text
        level_2_name=t.text
    elif t.name=="h3":
        raw=t.text
        level_2_code=re.sub(r"(.*)\((.*)\)",r"\2",raw) #正则表达式:模式字符串:(.*)\((.*)\);被替换字符串"\2";被处理字符串:raw
        level_2_name=re.sub(r"(.*)\((.*)\)",r"\1",raw)
    elif t.name=="h4":
        raw=t.text
        level_3_code=re.sub(r"(.*) \((.*)\)",r"\1",raw)
        level_3_name=re.sub(r"(.*) \((.*)\)",r"\2",raw)  # 首位为要替换的,\1和\2是要替换成的
    elif t.name=="p":
        notes=t.text
        level_1_names.append(level_1_name)
        level_2_names.append(level_2_name)
        level_2_codes.append(level_2_code)
        level_3_names.append(level_3_name)
        level_3_codes.append(level_3_code)
        level_3_notes.append(notes)

#根据以上信息生成dataframe格式的数据
df_taxonomy=pd.DataFrame({
    'group_name':level_1_names,
    'archive_name':level_2_name,
    'archive_id':level_2_codes,
    'category_name':level_3_names,
    'categories':level_3_codes,
    'category_description':level_3_notes
})

#按照 "group_name" 进行分组,在组内使用 "archive_name" 进行排序
df_taxonomy.groupby(["group_name","archive_name"])
df_taxonomy

在这里插入图片描述

4.统计计算机方向论文

连接原来的论文数据与论文类别

_df = data1.merge(df_taxonomy, on="categories", how="left").drop_duplicates(["id","group_name"]).groupby("group_name").agg({"id":"count"}).sort_values(by="id",ascending=False).reset_index()

_df

在这里插入图片描述

5.可视化

fig = plt.figure(figsize=(15,12))
explode = (0, 0, 0, 0.2, 0.3, 0.3, 0.2, 0.1) 
plt.pie(_df["id"],  labels=_df["group_name"], autopct='%1.2f%%', startangle=160, explode=explode)
plt.tight_layout()
plt.show()

在这里插入图片描述
仅保留计算机科学类论文,并统计该大类下,细分类别论文数随时间的变化

group_name="Computer Science"
cats = data.merge(df_taxonomy, on="categories").query("group_name == @group_name")
cats.groupby(["year","category_name"]).count().reset_index().pivot(index="category_name", columns="year",values="id") 

在这里插入图片描述

知识点总结:

  1. split+for循环,用于拆分同一字段内多值的情况;
  2. len(),配合上一步,获得所有枚举值
  3. 时间类型数据格式转换+获取年份数据:pd.to_datetime(被转换字段).dt.year
  4. groupby
  5. reset_index 重置索引
  6. 爬虫
  7. 正则
  8. merge

正则举例

# 插播 正则举例
import re 
phone="2004-959-559 # 这是一个电话号码" 

#删除注释
num=re.sub(r'#.*$','',phone)  #匹配从#开始,$-匹配到末尾/匹配行尾;替换为空值;.*贪婪匹配
print("电话号码:",num)

#移除非数字内容
num=re.sub(r'\D',"",phone)  # \D匹配所有数字内容

在这里插入图片描述

#指定保留哪一部分
#就我们的代码来说
raw='Astrophysics(astro-ph)'
raw1=re.sub(r"(.*)\((.*)\)",r"\1",raw)  # \1或\2是啥?- 要第几位的
raw1


raw2=re.sub(r"(.*)\((.*)\)",r"\2",raw)  # \1或\2是啥?- 要第几位的
raw2

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值