在 Neo4j 和 Python 中处理节点创建的 NaN 值
Handling NaN values for node creation in Neo4j and Python
当遍历 DataFrame 时,neo4j 创建 "NaN" 属性的节点时遇到这个小问题。基本上我有一个如下所示的 DataFrame:
member_id | attributed_provider
--------- | -------------------
1234 | 00A1A
5628 | G1378
2452 | NaN
1683 | 42419
9572 | NaN
然后我遍历我的 DataFrame 来创建我的节点和关系。我的节点将是成员和提供者。该关系将是 "attribution" 关系。这是我的代码:
for row in df.itertuples():
session.run("MERGE (mbr:Member {memberID: {memberID}) \
MERGE (pvdr:Provider {providerID: {provID} \
MERGE (mbr)-[:ATTRIBUTED]-(pvdr)",
{"memberID": row[1], "provID": row[2]})
现在,当我去我的 Neo4j 浏览器检查数据是如何创建的时,我注意到创建了带有 NaN 的提供者,但更奇怪的是这些 NaN 提供者的多个节点被创建了,而实际上只有一个应该因为我正在使用 MERGE 命令而被创建。理想情况下,我什至不希望创建这些 NaN 提供程序节点,因此我尝试使用以下方法在 Neo4j 端删除它们:
MATCH (pvdr:Provider) WHERE pvdr.providerID = "NaN" DELETE pvdr
然而,尽管在浏览器中将 "NaN" 显示为 providerID 值,但 Neo4j 根本无法匹配它们。然后我尝试了:
MATCH (pvdr:Provider) WHERE pvdr.providerID is NULL DELETE pvdr
同样,没有这样的比赛。
因此,我有两个问题:
1) 我如何使用 Cypher QL 匹配这些 NaN 提供程序?
2) 在 Python 的 node/relationship 创作部分有没有更好的方法来编写我的代码?
作为我第二个问题的后续,我使用 pd.notnull 检查来更改我的脚本,但我可以想象当我为 NaN 求值时我必须编写的 if 语句的数量扩展到更大的数据集,所以再一次,有没有更好的方法来做到这一点:
# Is there a better way to do this without doing the pd.notnull check?
for row in df.itertuples():
if pd.notnull(row[2]):
session.run("MERGE (mbr:Member {memberID: {memberID}) \
MERGE (pvdr:Provider {providerID: {provID} \
MERGE (mbr)-[:ATTRIBUTED]-(pvdr)",
{"memberID": row[1], "provID": row[2]})
else:
session.run("MERGE (mbr:Member {memberID: {memberID})",
{"memberID": row[1]})
仅供参考,我使用的是官方 Neo4j Python 驱动程序。
似乎没有有效处理 NaN 的解决方案。我想出的最接近的解决方案是定义一个自定义函数,如果值为 np.nan,则 returns 和 None。但是,当将其传递到 Neo4j 会话时,它仍然创建了一个 属性,但该 属性.
的字符串为空
最后,我只是创建了一个 CSV 文件并使用了 Neo4j 的 LOAD CSV
命令。我不得不做多次传球。前 2 次通过创建我的成员和提供者节点。然后最后一次执行条件 NULL 检查以创建关系。 LOAD CSV
运行 也比使用 Python 方法更快。
// Create members
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
CREATE (mbr:Member {memberID: row.member_id})
// Create providers
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
CREATE (mbr:Provider {providerID: row.attributed_provider})
// Create member-provider relationships
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
FOREACH (x IN CASE WHEN row.attributed_provider IS NULL THEN [] ELSE [1] END |
MERGE (mbr:Member {memberID: row.member_id})
MERGE (pvdr:Provider {providerID: row.attributed_provider})
MERGE (mbr)-[:ATTRIBUTED_WITH]-(pvdr)
)
当遍历 DataFrame 时,neo4j 创建 "NaN" 属性的节点时遇到这个小问题。基本上我有一个如下所示的 DataFrame:
member_id | attributed_provider
--------- | -------------------
1234 | 00A1A
5628 | G1378
2452 | NaN
1683 | 42419
9572 | NaN
然后我遍历我的 DataFrame 来创建我的节点和关系。我的节点将是成员和提供者。该关系将是 "attribution" 关系。这是我的代码:
for row in df.itertuples():
session.run("MERGE (mbr:Member {memberID: {memberID}) \
MERGE (pvdr:Provider {providerID: {provID} \
MERGE (mbr)-[:ATTRIBUTED]-(pvdr)",
{"memberID": row[1], "provID": row[2]})
现在,当我去我的 Neo4j 浏览器检查数据是如何创建的时,我注意到创建了带有 NaN 的提供者,但更奇怪的是这些 NaN 提供者的多个节点被创建了,而实际上只有一个应该因为我正在使用 MERGE 命令而被创建。理想情况下,我什至不希望创建这些 NaN 提供程序节点,因此我尝试使用以下方法在 Neo4j 端删除它们:
MATCH (pvdr:Provider) WHERE pvdr.providerID = "NaN" DELETE pvdr
然而,尽管在浏览器中将 "NaN" 显示为 providerID 值,但 Neo4j 根本无法匹配它们。然后我尝试了:
MATCH (pvdr:Provider) WHERE pvdr.providerID is NULL DELETE pvdr
同样,没有这样的比赛。
因此,我有两个问题:
1) 我如何使用 Cypher QL 匹配这些 NaN 提供程序?
2) 在 Python 的 node/relationship 创作部分有没有更好的方法来编写我的代码?
作为我第二个问题的后续,我使用 pd.notnull 检查来更改我的脚本,但我可以想象当我为 NaN 求值时我必须编写的 if 语句的数量扩展到更大的数据集,所以再一次,有没有更好的方法来做到这一点:
# Is there a better way to do this without doing the pd.notnull check?
for row in df.itertuples():
if pd.notnull(row[2]):
session.run("MERGE (mbr:Member {memberID: {memberID}) \
MERGE (pvdr:Provider {providerID: {provID} \
MERGE (mbr)-[:ATTRIBUTED]-(pvdr)",
{"memberID": row[1], "provID": row[2]})
else:
session.run("MERGE (mbr:Member {memberID: {memberID})",
{"memberID": row[1]})
仅供参考,我使用的是官方 Neo4j Python 驱动程序。
似乎没有有效处理 NaN 的解决方案。我想出的最接近的解决方案是定义一个自定义函数,如果值为 np.nan,则 returns 和 None。但是,当将其传递到 Neo4j 会话时,它仍然创建了一个 属性,但该 属性.
的字符串为空最后,我只是创建了一个 CSV 文件并使用了 Neo4j 的 LOAD CSV
命令。我不得不做多次传球。前 2 次通过创建我的成员和提供者节点。然后最后一次执行条件 NULL 检查以创建关系。 LOAD CSV
运行 也比使用 Python 方法更快。
// Create members
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
CREATE (mbr:Member {memberID: row.member_id})
// Create providers
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
CREATE (mbr:Provider {providerID: row.attributed_provider})
// Create member-provider relationships
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///dbt_enr_unique.csv" AS row
FOREACH (x IN CASE WHEN row.attributed_provider IS NULL THEN [] ELSE [1] END |
MERGE (mbr:Member {memberID: row.member_id})
MERGE (pvdr:Provider {providerID: row.attributed_provider})
MERGE (mbr)-[:ATTRIBUTED_WITH]-(pvdr)
)