论文作者统计
任务说明
任务主题:论⽂作者统计,统计所有论⽂作者出现评率Top10的姓名;
任务内容:论⽂作者的统计、使⽤ Pandas 读取数据并使⽤字符串操作;
任务成果:学习 Pandas 的字符串操作;
分析说明
- 从上述情况来看,我们要使用到pandas中关于字符串中的处理方法。
这里可以进行参考( )
- 根据任务目的我们可以知道,我们要统计的是论文作者的名称和排名。
作者名称 = 字符串的提取和筛选;
作者排名 = 对次数进行统计并排序 ;
选出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() 方法的使用
代码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参数表
还要注意:修改图配置时的设置方式