组队学习笔记Task1:论文数据统计

数据分析第一次组队学习笔记——Lizzy

@Datawhale

Task1:论文数据统计

  • 学习主题:论文数量统计(数据统计任务),统计2019年全年,计算机各个方向论文数量;
  • 学习内容:赛题理解、Pandas读取数据、数据统计 ;
  • 学习成果:学习Pandas基础;

1.1读取论文json文件

json:由于论文数据是一种json格式,所以需要import json这个模块来读取它们,将他们读取成python的内置数据结构,

json.loads()方法可以将读取到的每一行利用append传给列表对象

由于数据集过大,这里我读取了前100000个论文的数据,并对它们进行统计,具体的代码如下:

#首先导入需要使用的包
import pandas as pd#用于数据处理
#然后我用基本的文件操作读取了前100000个论文,并利用DataFrame的head()方法来显示其中的前五行,代码如下
data=[]
num=0
with open("D:\\arxiv-metadata-oai-snapshot.json",'r')as f:
    for line in f:
        data.append(json.loads(line))
        num+=1
        if num >99999:
            break
data=pd.DataFrame(data)
data.shape
data.head()

在这里插入图片描述

可以发现,一共有14个标签,分别对应14个特征数

1.2数据预处理

对catagories这个特征进行分析,这里采用了describe方法(),这是一种简单的描述方法,能一次性产生多种汇总性统计

对于数值型数据和非数值型数据,它会产生不同的输出,这里的种类不是数值型数据,我们根据代码分析种类这一特征,

data['categories'].describe()

在这里插入图片描述

count为计数,unique为唯一值,top为出现频率最高的种类,freq为这个种类出现的频率,通过分析可以发现,前十万个数据中,第6068个种类只出现了一次,出现频率最高的一种种类是astro-ph(天体物理学),由于我们只需要2019年的数据,因此我们需要对数据进行第一次预处理,代码如下:

#这个操作首先提取出时间这一列,然后将它转化为datatime格式,这是pandas自己内置的一种数据类型
data['year']=pd.to_datetime(data['update_date']).dt.year#只提取其中的年份,此时也新建了一列'year’,
del data["update_date"]
data=data[data'year'>=2019]#删除2019年之前的数据
data.reset_index(drop=True, inplace=True)
data

这里我没有用过reset_index,只用过reindex,于是查找了他们之间的区别,reindex是将列或者行重新整理一遍,reset_index是将索引重新整理一遍,因为当我们进行删除操作时,可能会使得数据不再是连续的数据,采用reset_index操作后,原来的index会变成新的一列,如果不想显示出来,可以传一个参数drop=True,这个参数默认是false,还有一个参数是inplace,它的意义是重新建一个,还是在原有的DataFrame上进行修改,inplace默认是false,也就是新建对象。

通过筛选,可以得到新的2019年的数据:

在这里插入图片描述

再筛选计算机领域的数据,并且只保留year,id,categories三个列

data=data[['id','categories','year']]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1RbUZkid-1610544850026)(C:\Users\李子毅\AppData\Roaming\Typora\typora-user-images\image-20210113192015245.png)]

1.3爬取论文的种类

爬虫这方面只用过BeautifulSoup,对正则还不太了解- -

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)
    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" 进行排序,返回一个层次化的列表
df_taxonomy.groupby(["group_name","archive_name"])
df_taxonomy

groupby函数:按照某一个索引进行分组,它可以接受多种参数,类似于Excel中的筛选操作

然后,将种类的DateFrame和论文数据的DataFrame共同的属性“categories”进行合并,并以并以 “group_name” 作为类别进行统计,统计结果放入 “id” 列中并排序。

这里重点补充一下merge方法的用法,因为个人感觉非常强大

merge函数:用于合并和链接操作:例如pd.merge(df1,df2),连接时,最好显示的指定键,例如 on=‘key’,

另外,还有一个参数how,它四种类型的值,‘inner’,‘outer’,‘left’,‘right’,分别代表不同的合并基准:交集,并集,左表,右表

_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()
#drop_duplicates->去重操作
#agg->列上以数值进行聚合
#sort_values->排序操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MUxQ8LSJ-1610544850028)(C:\Users\李子毅\AppData\Roaming\Typora\typora-user-images\image-20210113194446493.png)]

比起示例代码中众多的种类,我觉得这里是因为相同种类的论文大多因为排序聚集在一起,所以说种类有限

1.4数据分析和可视化

这里主要使用了matplotlib这个模块进行基本的可视化操作,代码大致如下:

import matplotlib.pyplot as plt#导入画图模块
fig=plt.figure(figsize=(15,12))#以窗口的格式展示,窗口大小为(15,12)
plt.pie(_df['id'],labels=_df['group_name'],autopct='%1.1f',explode=(0,0,0.2))#创建一个饼图
plt.tight_layout()#自动调节参数,使图片填充整个图
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9eJ7yBxp-1610544850030)(C:\Users\李子毅\AppData\Roaming\Typora\typora-user-images\image-20210113200622336.png)]

这里要用到创建一个饼图,关于pie()函数的参数详解如下:

x       :(每一块)的比例,如果sum(x) > 1会使用sum(x)归一化;
labels  :(每一块)饼图外侧显示的说明文字;
explode :(每一块)离开中心距离;
startangle :起始绘制角度,默认图是从x轴正方向逆时针画起,如设定=90则从y轴正方向画起;
shadow  :在饼图下面画一个阴影。默认值:False,即不画阴影;
labeldistance :label标记的绘制位置,相对于半径的比例,默认值为1.1, 如<1则绘制在饼图内侧;
autopct :控制饼图内百分比设置,可以使用format字符串或者format function
        '%1.1f'指小数点前后位数(没有用空格补齐);
pctdistance :类似于labeldistance,指定autopct的位置刻度,默认值为0.6;
radius  :控制饼图半径,默认值为1;counterclock :指定指针方向;布尔值,可选参数,默认为:True,即逆时针。将值改为False即可改为顺时针。wedgeprops :字典类型,可选参数,默认值:None。参数字典传递给wedge对象用来画一个饼图。例如:wedgeprops={'linewidth':3}设置wedge线宽为3。
textprops :设置标签(labels)和比例文字的格式;字典类型,可选参数,默认值为:None。传递给text对象的字典参数。
center :浮点类型的列表,可选参数,默认值:(0,0)。图标中心位置。
frame :布尔类型,可选参数,默认值:False。如果是true,绘制带有表的轴框架。
rotatelabels :布尔类型,可选参数,默认为:False。如果为True,旋转每个label到指定的角度。

好,接下来进入最后一步,不过我想换一个目标,改为统计物理学领域2019年之后的paper数量,同样使用emerge函数,不过由于本人对物理学领域不太了解,所以不再进行数据分析的过程,

最终的代码如下:

group_name="Physics"
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")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAXwXj1v-1610544850031)(C:\Users\李子毅\AppData\Roaming\Typora\typora-user-images\image-20210113201741809.png)]

最多的好像叫高能物理学,不太懂了hhh

猜你喜欢

转载自blog.csdn.net/weixin_45717055/article/details/112592874