如何在python pandas中有效地生成一个特殊的共同作者网络?

时间:2015-12-31 18:48:54

标签: python networking pandas graph

我尝试根据文章表格生成个别作者的网络图。我开始的表是关于"主要作者"和#34;共同作者"的单一栏目。由于每篇文章最多可包含5位作者,因此文章行可能会重复:

| paper_ID | project_name | lead_id | co_lead_id | published |
|----------+--------------+---------+------------+-----------|
|     1234 | "fubar"      |     999 |        555 | yes       |
|     1234 | "fubar"      |     999 |        234 | yes       |
|     1234 | "fubar"      |     999 |        115 | yes       |
|     2513 | "fubar2"     |     765 |        369 | no        |
|     2513 | "fubar2"     |     765 |        372 | no        |
|     5198 | "fubar3"     |     369 |        325 | yes       |

我的最终目标是拥有一个节点表,其中每一行都是唯一的作者,以及一个边表,其中每一行包含源和目标author_id列。边表是微不足道的,因为我只能使用article表的必需列创建数据帧。

例如,对于上表,我将得到以下节点表:

| author_id | is_published |
|-----------+--------------|
|       999 | yes          |
|       555 | yes          |
|       234 | yes          |
|       115 | yes          |
|       765 | no           |
|       369 | yes          |
|       372 | no           |
|       325 | yes          |

注意" is_published"显示作者是否曾在至少一篇已发表的论文中担任主要成员或共同作者。这是我在有效创建节点表时遇到麻烦的地方。目前,我遍历文章表中的每一行,并检查节点表中是否存在作者以及是否打开" is_published"旗。请参阅以下代码段作为示例:

articles = pd.read_excel('excel_file_with_articles_table')
nodes = pd.DataFrame(columns=('is_published'))
nodes.index.name = 'author_id'
for row in articles.itertuples():
    if not row.lead_id in nodes.index:
        author = pd.Series([False], index=["is_published"], name=row.lead_id)
        pi_nodes = pi_nodes.append(author)
    if not row.co_lead_id in nodes.index:]
        investigator = pd.Series([False], index=["is_published"], name=row.co_lead_id)
        pi_nodes = pi_nodes.append(investigator)
    if row.published == "yes":
        pi_nodes.at[row.lead_id,"is_published"]=True
        pi_nodes.at[row.co_lead_id,"is_published"]=True

对于我的数据集(有数万行),这有点慢,我知道在使用pandas数据帧时应该尽可能避免循环。我觉得大熊猫apply功能可能能够满足我的需求,但我对如何实现它感到茫然。

1 个答案:

答案 0 :(得分:1)

df作为您的第一个DataFrame,您应该能够:

nodes = pd.concat([df.loc[:, ['lead_id', 'is_published']].rename(columns={'lead_id': 'author_id'}, df.loc[:, ['co_lead_id', 'is_published']].rename(columns={'co_lead_id': 'author_id'}]).drop_duplicates()

获取author_idco_author_id的唯一列表及其各自的is_published信息。

如果还有is_published=True条目,则仅保留False

nodes = nodes.sort_values('is_published', ascending=False).drop_duplicates(subset=['author_id'])

.sort_values()会在True之前对==1 False进行排序,默认情况下.drop_duplicates()会保留第一次出现(see docs)。通过这个添加,我猜你不再需要第一个.drop_duplicates()了。