学术论文趋势分析-论文作者分析Task2

任务说明

任务主题:论⽂作者统计,统计所有论⽂作者出现评率Top10的姓名;

任务内容:论⽂作者的统计、使⽤ Pandas 读取数据并使⽤字符串操作;

任务成果:学习 Pandas 的字符串操作;

分析说明

  1. 从上述情况来看,我们要使用到pandas中关于字符串中的处理方法。

这里可以进行参考( )

  1. 根据任务目的我们可以知道,我们要统计的是论文作者的名称和排名。
    作者名称 = 字符串的提取和筛选;
    作者排名 = 对次数进行统计并排序 ;
    选出10% = 对作者名称的总数进行统计,并且对取出总数的10%的比例。

那么针对以上这些分析,我们便开始数据处理工作:

数据的处理步骤

首先我们可以查看一下原始数据:

# 导入所需的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-2019.json", 'r') as f: 
    for idx, line in enumerate(f): 
#         print(idx)
#         print(line)
        # 读取前100行,如果读取所有数据需要8G内存
        if idx >= 100:
            
            break
        
        data.append(json.loads(line))
        
data = pd.DataFrame(data) #将list变为dataframe格式,方便使用pandas进行分析
data.head()
id	submitter	authors	title	comments	journal-ref	doi	report-no	categories	license	abstract	versions	update_date	authors_parsed
0	0704.0297	Sung-Chul Yoon	Sung-Chul Yoon, Philipp Podsiadlowski and Step...	Remnant evolution after a carbon-oxygen white ...	15 pages, 15 figures, 3 tables, submitted to M...	None	10.1111/j.1365-2966.2007.12161.x	None	astro-ph	None	We systematically explore the evolution of t...	[{'version': 'v1', 'created': 'Tue, 3 Apr 2007...	2019-08-19	[[Yoon, Sung-Chul, ], [Podsiadlowski, Philipp,...
1	0704.0342	Patrice Ntumba Pungu	B. Dugmore and PP. Ntumba	Cofibrations in the Category of Frolicher Spac...	27 pages	None	None	None	math.AT	None	Cofibrations are defined in the category of ...	[{'version': 'v1', 'created': 'Tue, 3 Apr 2007...	2019-08-19	[[Dugmore, B., ], [Ntumba, PP., ]]
2	0704.0360	Zaqarashvili	T.V. Zaqarashvili and K Murawski	Torsional oscillations of longitudinally inhom...	6 pages, 3 figures, accepted in A&A	None	10.1051/0004-6361:20077246	None	astro-ph	None	We explore the effect of an inhomogeneous ma...	[{'version': 'v1', 'created': 'Tue, 3 Apr 2007...	2019-08-19	[[Zaqarashvili, T. V., ], [Murawski, K, ]]
3	0704.0525	Sezgin Ayg\"un	Sezgin Aygun, Ismail Tarhan, Husnu Baysal	On the Energy-Momentum Problem in Static Einst...	This submission has been withdrawn by arXiv ad...	Chin.Phys.Lett.24:355-358,2007	10.1088/0256-307X/24/2/015	None	gr-qc	None	This paper has been removed by arXiv adminis...	[{'version': 'v1', 'created': 'Wed, 4 Apr 2007...	2019-10-21	[[Aygun, Sezgin, ], [Tarhan, Ismail, ], [Baysa...
4	0704.0535	Antonio Pipino	Antonio Pipino (1,3), Thomas H. Puzia (2,4), a...	The Formation of Globular Cluster Systems in M...	32 pages (referee format), 9 figures, ApJ acce...	Astrophys.J.665:295-305,2007	10.1086/519546	None	astro-ph	None	The most massive elliptical galaxies show a ...	[{'version': 'v1', 'created': 'Wed, 4 Apr 2007...	2019-08-19	[[Pipino, Antonio, ], [Puzia, Thomas H., ], [M...

注意:我们写的读取数据的函数,其中它的类别为:

authors:论文作者;(作者是谁)
authors_parsed:作者的信息(作者信息)
id:arXiv ID,可用于访问论文;(针对哪篇篇论文)
categories:论文在 arXiv 系统的所属类别或标签;(针对哪一个类)

在原始arxiv数据集中论⽂作者 authors 字段是⼀个字符串格式,其中每个作者使⽤逗号进⾏分隔分。

那么我们的工作便是:

1. 通过逗号把名字不同的数据进行分割 ,   应该会使用:

	字符串名. split(",")
	
2. 然后把论文作者的非常规字符进行剔除。

那么针对这两个工作,我们进行如下代码:

数据读取

# 导入所需的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 #画图工具

def readArxivFile(path, columns=['id', 'submitter', 'authors', 'title', 'comments', 'journal-ref', 'doi',
       'report-no', 'categories', 'license', 'abstract', 'versions',
       'update_date', 'authors_parsed'], count=None):
    '''
    定义读取文件的函数
        path: 文件路径
        columns: 需要选择的列
        count: 读取行数
    '''
    
    data  = []
    with open(path, 'r') as f: 
        for idx, line in enumerate(f): 
            if idx == count:
                break
                
            d = json.loads(line)
            d = {col : d[col] for col in columns}
            data.append(d)

    data = pd.DataFrame(data)
    return data

data = readArxivFile('arxiv-metadata-oai-2019.json', 
                     ['id', 'authors', 'categories', 'authors_parsed'],
                    100000)

data.head()
	id	authors	categories	authors_parsed
0	0704.0297	Sung-Chul Yoon, Philipp Podsiadlowski and Step...	astro-ph	[[Yoon, Sung-Chul, ], [Podsiadlowski, Philipp,...
1	0704.0342	B. Dugmore and PP. Ntumba	math.AT	[[Dugmore, B., ], [Ntumba, PP., ]]
2	0704.0360	T.V. Zaqarashvili and K Murawski	astro-ph	[[Zaqarashvili, T. V., ], [Murawski, K, ]]
3	0704.0525	Sezgin Aygun, Ismail Tarhan, Husnu Baysal	gr-qc	[[Aygun, Sezgin, ], [Tarhan, Ismail, ], [Baysa...
4	0704.0535	Antonio Pipino (1,3), Thomas H. Puzia (2,4), a...	astro-ph	[[Pipino, Antonio, ], [Puzia, Thomas H., ], [M...

数据统计

首先我们来明确一下任务:统计论文作者,然后统计数量,然后计算10%的数据,并输出。

由上面我们已经得到了数据集,也已经取出了论文中作者的名字,接下来我们便是针对这种情况统计论文作者出现的频次。然后计算10%的数据。

这里为了节约时间,我们选取部分类别数据进行处理:

# 选择类别为cs.CV下面的论文
data2 = data[data['categories'].apply(lambda x: 'cs.CV' in x)]

# 拼接所有作者
all_authors = sum(data2['authors_parsed'], [])

上面看出,我们选取的是 cs.CV类别。选取方法:

1. 我们要选择某个类别,那么我们需要把这个类别同所有类别比对,相同的则选出来,类似于:
list_name = ["a", "b", "c", "d", "e"]

if "c" in list_name:
    list_name2 = "c在list_name中"
    
print(list_name2)
c在list_name中

同理,我们可以使用这个思路,那么:

判断我们要选择的类别,是不是在 x 中,如果是,那么返回True.

data["categories"].apply(lambda x: "cs.CV" in x)
0        False
1        False
2        False
3        False
4        False
         ...  
99995    False
99996    False
99997    False
99998    False
99999    False
Name: categories, Length: 100000, dtype: bool

然后,在把这些判断后的结果,作为元素,从data中取出。

data2 = data[data["categories"].apply(lambda x: "cs.CV" in x)]

data2.head()
	id	authors	categories	authors_parsed
531	0802.1412	Mahesh Pal	cs.NE cs.CV	[[Pal, Mahesh, ]]
1408	0905.1235	Serguei A. Mokhov, Stephen Sinclair, Ian Cl\'e...	cs.SD cs.CL cs.CV cs.MM cs.NE	[[Mokhov, Serguei A., , for the MARF R&D Group...
3231	1107.2875	Chris Aholt, Bernd Sturmfels, Rekha Thomas	math.AG cs.CV	[[Aholt, Chris, ], [Sturmfels, Bernd, ], [Thom...
4120	1203.0905	Jos\'e I. Ronda, Antonio Vald\'es and Guillerm...	cs.CV	[[Ronda, José I., ], [Valdés, Antonio, ], [Gal...
4378	1206.2627	Tanaya Guha and Rabab K. Ward	cs.CV	[[Guha, Tanaya, ], [Ward, Rabab K., ]]

从这里我们再来看一下,

首先这类别是 cs.CV方向的数据,然后明确论文作者的名字(authors) 和 信息(authors_parsed)

all_authors = sum(data2['authors_parsed'], [])

这里有疑问了? 为什么这里可以使用sum()进行连接?

下面我们将通过一个例子来进行理解:

list_name = ["a", "b", "c", "d", "e"]

sum(list_name, [])

上面的这种写法会报错:

TypeError: can only concatenate list (not "str") to list

查看**sum() 函数: 是对序列进行求和计算。**

这里的序列指的是: 可迭代对象,如:列表、元组、集合。

那么又会问了:上面的list_name也是列表呀,也是可迭代对象呀,为什么不能进行计算呢?

我们来看一下报错的原因:显示的是,这个里面的元素是字符串,而不是列表

那么问题就清楚了,sum() 函数使用的时候,变量中的元素应该是——可迭代对象

那么如何对 list_name 进行运算呢?

list_name 是 可迭代对象,把它变成元素即可,那么只需要加个中括号

sum([list_name], [])
['a', 'b', 'c', 'd', 'e']

应用这个思路,我们来看一下,data2[‘authors_parsed’] 的类型

type(data2['authors_parsed'][531])

这里写531的原因是,原来的下标未进行改变。

list

那么,便可以使用 sum() 函数

all_author = sum(data2['authors_parsed'], [])

type(all_authors)    #  类型是list
all_authors[:5]
[['Pal', 'Mahesh', ''],
 ['Mokhov', 'Serguei A.', '', 'for the MARF R&D Group'],
 ['Sinclair', 'Stephen', '', 'for the MARF R&D Group'],
 ['Clément', 'Ian', '', 'for the MARF R&D Group'],
 ['Nicolacopoulos', 'Dimitrios', '', 'for the MARF R&D Group']]

从这里我们可以看出,这些信息是一个包含所有姓名的列表,他们是在一起的。列表中的信息也是列表

接下来进行如下处理:

[' '.join(x) for x in all_authors]

然后取出一部分元素查看:

[' '.join(x) for x in all_authors][:5]
['Pal Mahesh ',
 'Mokhov Serguei A.  for the MARF R&D Group',
 'Sinclair Stephen  for the MARF R&D Group',
 'Clément Ian  for the MARF R&D Group',
 'Nicolacopoulos Dimitrios  for the MARF R&D Group']

这样看出来区别了,我们将这些转化成了 元素类型是 str类型的列表。

# 拼接所有的作者
authors_names = [' '.join(x) for x in all_authors]
authors_names = pd.DataFrame(authors_names)
# print(authors_names)
# # 根据作者频率绘制直方图
plt.figure(figsize=(10, 6))
authors_names[0].value_counts().head(10).plot(kind='barh')

# 修改图配置
names = authors_names[0].value_counts().index.values[:10]
_ = plt.yticks(range(0, len(names)), names)
plt.ylabel('Author')
plt.xlabel('Count')

接下来统计姓名姓,也就是authors_parsed字段中作者第一个单词:

authors_lastnames = [x[0] for x in all_authors]
authors_lastnames = pd.DataFrame(authors_lastnames)

plt.figure(figsize=(10, 6))
authors_lastnames[0].value_counts().head(10).plot(kind='barh')

names = authors_lastnames[0].value_counts().index.values[:10]
_ = plt.yticks(range(0, len(names)), names)
plt.ylabel('Author')
plt.xlabel('Count')

以上这两个是取出符合条件的姓名。

进行如下理解:

[' '.join(x) for x in all_authors]  按照空格将 all_authors 中的值按照空格的方式进行连接。
"某种连接方式".join(要连接的元素或变量)  =  用某种方式对数据进行连接

join() 方法的使用

python中 使用join()方法

代码1 :

[' '.join(x) for x in all_authors][:5]
['Pal Mahesh ',
 'Mokhov Serguei A.  for the MARF R&D Group',
 'Sinclair Stephen  for the MARF R&D Group',
 'Clément Ian  for the MARF R&D Group',
 'Nicolacopoulos Dimitrios  for the MARF R&D Group']

代码2 :

s = []
for x in all_authors[:5]:
    b = " ".join(x)  # 这里只是起了连接作用
    s.append(b)  # 这里是在上一步的基础上执行添加元素操作
    
print(b)
print(s)
Nicolacopoulos Dimitrios  for the MARF R&D Group

['Pal Mahesh ', 'Mokhov Serguei A.  for the MARF R&D Group', 'Sinclair Stephen  for the MARF R&D Group', 'Clément Ian  for the MARF R&D Group', 'Nicolacopoulos Dimitrios  for the MARF R&D Group']

从上面的结果中看出,两个结果形式是不一样的。是什么原因呢?

type([' '.join(x) for x in all_authors][:5])

# list

这是一个列表,那 变量 s 也是一个列表呀,为什么输出情况不相同呢?

我们采用判断是否相等的思路判断它们两个是否是一致的:

s == [' '.join(x) for x in all_authors[:5]]
# True

因此是一样的:

print([x*2 for x in "abc"])

b = []
for x in "abc":
    b.append(x*2)
print(b)
['aa', 'bb', 'cc']
['aa', 'bb', 'cc']
authors_names[0].value_counts().head(10).plot(kind='barh')

这里的authors_names是DataFrame格式的数据, 其中authors_names数据为:

                                                      0
0                                           Pal Mahesh 
1             Mokhov Serguei A.  for the MARF R&D Group
2              Sinclair Stephen  for the MARF R&D Group
3                   Clément Ian  for the MARF R&D Group
4      Nicolacopoulos Dimitrios  for the MARF R&D Group
...                                                 ...
23122                                      Ma Xiaolong 
23123                                       Ye Shaokai 
23124                                        Yuan Geng 
23125                                      Ma Kaisheng 
23126                                      Wang Yanzhi 

[23127 rows x 1 columns]

这里要选出作者的数据:那么查看数据为列类别是 0 ,因此是 authors_names[0]

因为我们的目的是要统计前10% 的作者名称,那么我们要用pandas 中统计数据出现的频次问题。所以,我们使用 value_counts() 方法

下面对这个方法进行总结
参考文章:
(https://www.jb51.net/article/163795.htm)
(https://www.cnblogs.com/sxinfo/p/10385716.html)

value_counts() : 计算每个不同值有在该列中有多少重复值

使用方法:
数据名.value_counts(ascending = True 或 False)

在本任务中:

authors_names[0].value_counts().head(10)
Tao Dacheng           50
Van Gool Luc          27
Liu Wei               24
Zhang Lei             22
Wang Xiaogang         21
Navab Nassir          21
Darrell Trevor        21
Reid Ian              18
Davis Larry S.        17
Torr Philip H. S.     17
Name: 0, dtype: int64

前10名,然后进行可视化:

authors_names[0].value_counts().head(10).plot(kind='barh')

在这里插入图片描述

这里使用的是, .plot() 方法:

Series.plot(kind="绘制方式") , Series = 数据名
plt.plot() 

注意以上这两种方法是不同的。

plt.plot() 是用来绘制折线图
Series.plot(kind = “绘制方式”) 可以通过kind的选择,更换不同的选择方式。

参考文章:
【matplotlib】plot()kind参数表

plt.plot()函数解析

还要注意:修改图配置时的设置方式
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值