【Academic Trends】Task 01:论文数据统计_学了又忘的海伦的博客-程序员宅基地

技术标签: python  数据分析  

1. 任务背景

  • 任务主题:论文数量统计,即统计2019年全年计算机各个方向论文数量;
  • 任务内容:赛题的理解、使用 Pandas 读取数据并进行统计;

2. 数据集介绍

  • 数据集来源:https://www.kaggle.com/Cornell-University/arxiv
  • 数据集维度介绍
维度名称 定义
id arXiv ID,可用于访问论文
summitter 论文提交者
authors 论文作者
title 论文标题
comments 论文页数和图表等其他信息
journal-ref 论文发表的期刊的信息
doi 数字对象标识符
report-no 报告编号
categories 论文在arXiv系统的所属类别或标签
license 文章的许可证
abstract 论文摘要
versions 论文版本
authors_parsed 作者的信息

3. 具体代码实现

3.1导入package并读取原始数据

# 导入所需的package
import seaborn as sns #用于画图
from bs4 import BeautifulSoup #用于爬取arxiv的数据
import re #用于正则表达式,匹配字符串的模式
import requests #用于网络连接,发送网络请求,使用域名获取对应信息
import json #读取数据,我们的数据为json格式的
import pandas as pd #数据处理,数据分析
import matplotlib.pyplot as plt #画图工具
# 读入数据
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 #显示数据大小
data.head() #显示数据样例

3.1.1 自动关闭文件句柄的优势

  1. 有时对文件的隐藏引用仍然存在.如果在函数中抛出异常,则与异常关联的回溯包含对函数执行帧的引用,因此所有局部变量都会继续存在 – 即使在CPython中,这也可能使文件保持打开的时间超过预期.
  2. 打开许多文件时,您可能会用完文件描述符,因为您无法控制它们再次关闭的时间.
  3. Python 3.2或更高版本将为每个未关闭的文件引发ResourceWarning(此警告可以被禁用,但无论如何).

3.1.2 json函数

json.loads

json.loads 用于解码 JSON 数据。该函数返回 Python 字段的数据类型。

json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])

json类型转换到python的类型对照

JSON Python
object dict
array list
string unicode
number(int) int,long
number(real) float
true Ture
false False
null None

3.2 数据预处理

3.2.1 粗略统计论文的种类信息

pandas.DataFrame.decribe()
3.2.1.1 数据总体情况了解
data['categories'].describe()

#count     170618
#unique     15592
#top        cs.CV
#freq        5559
#Name: categories, dtype: object

'''
count:一列数据的元素个数;
unique:一列数据中元素的种类;
top:一列数据中出现频率最高的元素;
freq:一列数据中出现频率最高的元素的个数;
'''
3.2.1.2 划分独立数据集

判断在本数据集中出现多少种独立的数据集
从论文类别、时间进行划分独立数据集

# 所有的种类(独立的)

#split:将多类别使用 “ ”(空格)分开,组成list,然后使用for循环取出所有的类别(取出所有类别到一个列表中)
#set:将重复项去除得到最终所有的独立paper种类(去重)

unique_categories = set([i for l in [x.split(' ') for x in data["categories"]] for i in l])
len(unique_categories)
unique_categories
#根据时间对数据进行处理和筛选
data["year"] = pd.to_datetime(data["update_date"]).dt.year #将update_date从例如2019-02-20的str变为datetime格式,并提取处year
del data["update_date"] #删除 update_date特征,其使命已完成
data = data[data["year"] >= 2019] #找出 year 中2019年以后的数据,并将其他数据删除
# data.groupby(['categories','year']) 
#以 categories 进行排序,如果同一个categories 相同则使用 year 特征进行排序
data.reset_index(drop=True, inplace=True) #重新编号
data #查看结果

3.2.2 爬取康奈尔大学网站论文分类信息进行匹配

#爬取arXiv论文分类列表
#使用requests 和 bs4进行爬取和解析
#获取网页的文本数据(HTML内容)
website_url = requests.get('https://arxiv.org/category_taxonomy').text
print(website_url)

在这里插入图片描述

#爬取数据,这里使用lxml的解析器,加速
soup = BeautifulSoup(website_url,'lxml')

#找出 BeautifulSoup 对应的标签入口,定位爬取内容的模块,截取一段HTML
root = soup.find('div',{
    'id':'category_taxonomy_list'}) 
#选取模块内的tags的HTML内容
tags = root.find_all(["h2","h3","h4","p"], recursive=True) 

#初始化 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 = []

#对tags内容进行提取,放入不同的list
#了解标签有什么属性
#dir(tags[0])
#爬取思路:有h2的先把h2作为一二级标签,有h3的覆盖h2的二级标签

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
        #正则表达式:模式字符串:(.*)\((.*)\);被替换字符串"\2";被处理字符串:raw
        level_2_code = re.sub(r"(.*)\((.*)\)",r"\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)
    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_names,
    'archive_id' : level_2_codes,
    'category_name' : level_3_names,
    'categories' : level_3_codes,
    'category_description': level_3_notes
    })

#按照 "group_name" 进行分组,在组内使用 "archive_name" 进行排序
#不过由于网站本身也是按照archieve_name排序,爬取的时候按照group_name来爬取的,所以基本上没有区别
df_taxonomy.groupby(["group_name","archive_name"])
df_taxonomy

在这里插入图片描述groupby用法

3.2.3 正则讲解

3.2.3.1 公式

'''
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
其中pattern、repl、string为必选参数
'''
re.sub(pattern, repl, string, count=0, flags=0)

3.2.3.2 对于网页tag的匹配语句讲解

re.sub(r"(.*)\((.*)\)",r"\2",raw)

#raw = Astrophysics(astro-ph)
#output = astro-ph

解析和材料:

  • 正则中的模式字符串 pattern 的格式为 “任意字符” + “(” + “任意字符” + “)”。
  • 替换的字符串 repl 为第2个分组的内容。
  • 要被查找替换的原始字符串 string 为原始的爬取的数据。
  • 在线正则表达式测试的网站

3.4 数据分析及可视化

3.4.1 数据分析

#所有大类的paper数量分布
_df = data.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

以上语句有点复杂,所以拆开来看,并附上知识点

#以上进行分解解析
#左连接data和df_taxonomy
df1 = data.merge(df_taxonomy,on= 'categories',how = 'left')
df1.head()
#去重,看有没有id和group_name同时相同的行
df2 = df1.drop_duplicates(['id','group_name'])
df2.info()
df2.head()
#以group_name聚合统计,groupby后续一定要接计算方法/统计方法,agg for aggregate
#agg是统计函数,可以制定统计方法,如sum,max,min,count
df3 = df2.groupby('group_name').agg({
    'id':'count'})
df3
#降序排列
df4 = df3.sort_values(by = 'id',ascending = False)
df4
#重设索引
df5 = df4.reset_index()
df5

3.4.2 数据可视化

#画图
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()

在这里插入图片描述

  • 统计在计算机各个子领域2019年后的paper数量
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") 

画柱状图

#画柱状图
df_cats = cats.groupby(["year","category_name"]).count().reset_index().pivot(index="category_name", columns="year",values="id") 
num = df_cats.iloc[:,0].to_list()
df_cats.head()

labels = list(df_cats.index)
labels_no = range(len(labels))
label_list = pd.DataFrame(columns = ['label_no','label_name'])
label_list['label_no'] = labels_no
label_list['label_name'] = labels

x = np.arange(len(labels))
width = 0.35

plt.bar(labels_no,num)
plt.show()

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46462735/article/details/112461412

智能推荐

随便推点