问题:计算针对多个主题发表论文的人数
示例:
"pm"
有两篇论文,它们仅与Poo
相关,并且由于只有一个主题,因此不被认为是Physics
的一篇论文包含两(2)个主题(Amy
,Physics
),因此应该算在内Economics
有两篇论文,每篇论文都有不同的主题,因此应该算在内示例数据框:
Baa
| | id | name | has_published_papers |
|---|-----|------|-----------------------------------------|
| 0 | 100 | Amy | pp3524172 |
| 1 | 101 | Bla | pp0120888,pp0343660,pp0151738,pp0120631 |
| 2 | 102 | Foo | pp0134084,pp1262416,pp0120082,pp0117571 |
| 3 | 103 | Boo | pp0274558,pp0108872,pp1796960,pp0117509 |
| 4 | 104 | Soo | pp0120338,pp0993846,pp1375666,pp0407887 |
| 5 | 111 | Poo | pp0152095,pp1234567 |
| 6 | 112 | Baa | pp0237474,pp0152095 |
修改
理想的输出是| | paper_id | name | topics |
|----|-----------|-------------|--------------------|
| 30 | pp3524172 | research A | Physics, Economics |
| 40 | pp0189076 | research B | Math, Physics |
| 55 | pp0237474 | research C | Education |
| 68 | pp2729488 | research D | Physics, Math |
| 79 | pp0152095 | research Z | Physics |
| 99 | pp1234567 | research X | Physics |
,代表针对多个主题发表论文的人数
答案 0 :(得分:5)
您需要一些步骤来合并这些数据集。
您要做的第一件事是将has_published_papers
列拆分并扩展为多列:
authors_df = pd.DataFrame({
'id': [100, 101],
'name': ['Amy', 'Bla'],
'has_published_papers': ['pp3524172', 'pp0120888,pp0343660,pp0151738,pp0120631']
})
authors_df.has_published_papers.str.split(',', expand=True)
这将输出
0 1 2 3
0 pp3524172 None None None
1 pp0120888 pp0343660 pp0151738 pp0120631
然后,您可以将其连接到原始数据帧并融化它:
authors_papers_df = (
pd.concat([
authors_df.drop(columns=['has_published_papers']),
authors_df.has_published_papers.str.split(',', expand=True)
], axis=1)
.melt(['id', 'name'], value_name='paper_id')
.dropna(subset=['paper_id']))
这将输出准备好合并的漂亮数据框:
id name variable paper_id
0 100 Amy 0 pp3524172
1 101 Bla 0 pp0120888
3 101 Bla 1 pp0343660
5 101 Bla 2 pp0151738
7 101 Bla 3 pp0120631
您可以执行完全相同的拆分/扩展/融化管道来创建papers_topics数据框。
papers_topics_df = (
pd.concat([
papers_df.drop(columns=['topics']),
papers_df.topics.str.split(', ', expand=True)
], axis=1)
.melt(['paper_id', 'name'], value_name='topic')
.dropna(subset=['topic'])
)
然后您可以在paper_id
上进行合并。
authors_papers_topics_df = authors_papers_df.merge(papers_topics_df, on='paper_id')
现在您有了一个与主题,论文和作者相关的数据框。
要计算每个作者的独特主题,您可以使用:
authors_papers_topics_df.groupby('id')['topics'].nunique()
看到您的修改。要获取具有多个主题的作者数量,请使用:
np.sum(authors_papers_topics_df.groupby('id')['topics'].nunique() > 1)
答案 1 :(得分:2)
首先转换两个数据框:
您的第一个DataFrame( df )到具有单独行的DataFrame 对于每篇论文,并将论文ID作为索引:
paper = df.set_index('name').has_published_papers.str.split(',')\
.explode().reset_index(name='id').set_index('id')
结果是:
name
id
pp3524172 Amy
pp0120888 Bla
pp0343660 Bla
pp0151738 Bla
pp0120631 Bla
pp0134084 Foo
pp1262416 Foo
pp0120082 Foo
pp0117571 Foo
pp0274558 Boo
pp0108872 Boo
pp1796960 Boo
pp0117509 Boo
pp0120338 Soo
pp0993846 Soo
pp1375666 Soo
pp0407887 Soo
pp0152095 Poo
pp1234567 Poo
pp0237474 Baa
pp0152095 Baa
您的第二个DataFrame( df2 )归为Series,将每个主题行划分为 分成单独的元素,再以纸张ID作为索引:
topic = df2.set_index('paper_id').topics.str.split(', ').explode()
结果是:
paper_id
pp3524172 Physics
pp3524172 Economics
pp0189076 Math
pp0189076 Physics
pp0237474 Education
pp2729488 Physics
pp2729488 Math
pp0152095 Physics
pp1234567 Physics
Name: topics, dtype: object
然后:
执行此操作的代码是:
result = paper.join(topic).dropna().reset_index(drop=True)\
.drop_duplicates().groupby('name').count().reset_index()
获取:
name topics
0 Amy 2
1 Baa 2
2 Poo 1
要获得真正的最终结果,请检索具有 topics> 1 的行 并仅获取 name 列:
result.query('topics > 1').name
最终结果是:
0 Amy
1 Baa
Name: name, dtype: object
或者,如果您想获取简单的 pythonic 列表(而不是 Series ),
将.tolist()
添加到上述说明中,这次将得到:
['Amy', 'Baa']