【问题标题】:Generating a graph with Pandas from a CSV file using Python and dtypes of columns使用 Python 和列的 dtypes 从 CSV 文件生成带有 Pandas 的图形
【发布时间】:2021-04-04 02:52:24
【问题描述】:

这个问题可能是初级的。背景是这样的:我正在尝试从 CSV 文件在 Python 中构建图形。理想情况下,它看起来像这样:

这向我表明Sankey diagram 将是一个不错的选择,尽管我真正想到的是制作“路线图”或“高速公路图”之类的东西。我真正映射的是逻辑依赖关系:这里的节点代表定理,当一个定理的证明引用另一个定理时,应该在节点之间绘制一条边(从早期的定理 T“流动”到引用 T 的任何后面的定理)。

为此,我正在加载一个 CSV 文件,其中包含一列中的所有定理(节点),PM['pmnum'],以及边缘应将其连接到另一列的所有定理,即所有定理在证明中使用该节点的另一列 PM['pmproof']。

使用 pandas,很容易将 CSV 文件转换为 DataFrame。我的麻烦在于从 DataFrame 生成图形本身。当我使用

构建它时
G = nx.from_pandas_edgelist(PM, 'pmnum', 'pmproof')
nx.draw(G, with_labels=True)
plt.show(G)

图像如下所示:

我怀疑缺少边是由具有不同 dtype 的 DataFrame 的列产生的; PM['pmnum'] 列具有 dtype 浮点数,而 PM['pmprop'] 列具有 dtype 对象。这是因为当我跑步时

print(G.edges)

我得到一个很长的输出,其中包括这样的对:('1.2', 2.08), ('1.2', 2.4)。同样,当我运行时

print(G.nodes)

我在一个数组中得到一个长输出,其中包含看似不同类型的条目,例如 2.05、'1.6'、2.06、'2.04'。当我运行 print (PM.dtypes) 时,我得到 pmnum 有 dtype float64 而 pmproof 有 dtype 对象。

这又是由以下原因引起的:在初始 CSV 文件中,用于图形的两列包括一个浮点数和一个数组,例如,第 1 列有

1.2

并且第 2 列有(例如)

2.01、2.05、2.3

当我更改 DataFrame 以分离出该数组的每个条目时,这可能会导致 dtype 的差异。在那里,我首先分隔字符串,然后使用explode() 函数确保例如1.2 连接到每个条目2.01、2.05 和2.3(而不是连接到例如包含所有这些条目的数组)。

dtype 的差异是导致问题的原因吗?如果是这样,有没有办法解决它,例如,通过更改一列或另一列的 dtype?为了生成图表,列应该具有哪些 dtypes?下面是我的 Jupyter Notebook 中的代码。提前感谢您的帮助。编辑:还包括数据样本:https://ln.sync.com/dl/ecd0fa150/7wrdt3n4-xg4ca3jv-5f4tyyey-st9wp5jm

import pandas as pd
import plotly as pl
import plotly.graph_objects as go 
import networkx as nx
import numpy as np
import seaborn as sn
import dash as ds
import xmltodict
import csv
import unicodedata
import matplotlib.pyplot as plt
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import plotly.io as pio
pio.renderers.default='notebook'

%This is where I load the DataFrame.
PM = pd.read_csv('PM.csv', sep=',')

%This is where I explode the array to make sure the node has an edge for every entry of that array.
PM = pd.read_csv('PM.csv', sep=',')
PM['pmproof'] = PM['pmproof'].str.split(', ')
PM = PM.explode('pmproof')

%This is where I plot the graph
G = nx.from_pandas_edgelist(PM, 'pmnum', 'pmproof')
nx.draw(G, with_labels=True)
plt.show(G)

【问题讨论】:

  • 我建议粘贴来自PM.csv 的一些示例行,足以让 SO 用户运行此代码块并在其本地计算机上重现问题。
  • 是的,请从您的csv 发布示例数据。 df.head(20) 应该可以。
  • 感谢您指出这个遗漏。数据样本(约 30 行)现已通过可下载 CSV 文件的链接发布。
  • 在重现您的问题时,我发现边缘确实显示出来了。在您的情况下,它们很可能根本不可见,因为图表很小。
  • 非常感谢@RJAdriaansen。我现在看到在 nx.draw 函数中添加例如“linewidths=20”会使边缘出现。不幸的是,节点似乎被 from_pandas_edgelist 函数复制。理想情况下,通过将所有 PM.['pmnum'] 都设为节点,然后在 PM.['pmproof'] 中出现与 PM.['pmnum' 同一行中的节点时在这些节点之间绘制边来构建图]。是 dtypes 的差异导致节点重复,还是爆炸功能?如果不是,我的问题现在不同了,我想我会关闭这个问题并重新审视绘图板。

标签: python pandas dataframe csv graph


【解决方案1】:

感谢 RJ Adriaansen 的回答,我注意到边缘确实存在,但太薄而无法看到。我使用

将“pmproof”列更改为浮点数
PM['pmproof'] = PM.pmproof.astype(float)

事实证明,这删除了将边缘分开太多的重复节点。这是带有修复程序的快速生成的 Sankey 图(使用Ken Lok's genSankey function 快速构建):

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 2016-03-17
    • 2021-12-14
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    相关资源
    最近更新 更多