首页 > 解决方案 > 高效的数据框查找和提取

问题描述

我想通过 8 个坐标的 x,y,z 平均值计算质心。元素 ID 指的是立方体,而节点 ID 指的是立方体上的球体。我有一个数据框,其中包含元素 ID 和连接节点上的 ID。在另一个数据框中,我有节点 ID 及其坐标。为每个元素 ID 查找相邻节点坐标并基于这些计算立方体质心的最有效方法是什么?

包含元素 ID 和节点 ID 的 Dataframe 的数据结构

        Element ID  Node 1  Node 2  Node 3  ...  Node 5  Node 6  Node 7  Node 8
0           856395  764524  768124  767621  ...  766463  768139  767613  767612
1           856396  764524  767551  767621  ...  764525  767491  767622  768125
2           856397  764525  767491  767622  ...  764526  767431  767623  768126
3           856398  764526  767431  767623  ...  764527  767371  767624  768127
4           856399  764527  767371  767624  ...  764528  767311  767625  768128

包含节点 ID 和节点坐标的 Dataframe 的数据结构

        Node ID         X         Y         Z
0        764525  0.342972 -0.104031  6.499699
1        764526  0.342976 -0.104033  6.514697
2        764527  0.342979 -0.104034  6.529694
3        764528  0.342980 -0.104034  6.544691
4        764529  0.342981 -0.104035  6.559689

在此处输入图像描述

这可行,但真的很丑而且很慢:-(

append1 = pd.merge(df_element_ids_nodes,df_node_ids_coordinates, left_on="Node 1", right_on="Node ID")
append2 = pd.merge(append1,df_node_ids_coordinates, left_on="Node 2", right_on="Node ID")
append3 = pd.merge(append2,df_node_ids_coordinates, left_on="Node 3", right_on="Node ID")
append4 = pd.merge(append3,df_node_ids_coordinates, left_on="Node 4", right_on="Node ID")
append5 = pd.merge(append4,df_node_ids_coordinates, left_on="Node 5", right_on="Node ID")
append6 = pd.merge(append5,df_node_ids_coordinates, left_on="Node 6", right_on="Node ID")
append7 = pd.merge(append6,df_node_ids_coordinates, left_on="Node 7", right_on="Node ID")
append8 = pd.merge(append7,df_node_ids_coordinates, left_on="Node 8", right_on="Node ID")

print(append8)

df_results = pd.DataFrame(columns=["ElementId", "X", "Y", "Z"])
for index, row in append8.iterrows():
    centroid_x = (row[10] + row[14] + row[18] + row[22] + row[26] + row[30] + row[34] + row[38])/8
    centroid_y = (row[11] + row[15] + row[19] + row[23] + row[27] + row[31] + row[35] + row[39])/8
    centroid_z = (row[12] + row[16] + row[20] + row[24] + row[28] + row[32] + row[36] + row[40])/8
    Element_ID = row[0]
    df_results = df_results.append({"ElementId": int(Element_ID), "X": centroid_x, "Y": centroid_y, "Z": centroid_z}, ignore_index=True)


print(df_results)

标签: pandasdataframeperformance

解决方案


一种非常有效的方法是执行数据帧的数据帧连接。连接应该对 ID 进行排序,并对包含出现在主数据框中的每个所需 ID 的节点 ID 的数据帧的 ID 执行二分法。这个操作是O(n log n)及时完成的​​。在最好的情况下,它可以散列节点索引以及O(1)时完成。这里有两个例子:

# Case 1 -- discard the 'Node ID' field:
elementDataframe.set_index('Node ID').join(nodeDataframe.set_index('Node ID'))

# Case 2 -- do not discard the field and is simpler to use:
elementDataframe.merge(nodeDataframe, on='Node ID')

如果节点 ID 是连续的(并且如此排序),那么有一个更快的解决方案:您可以使用直接访问(如查找表)获取节点 ID,在您的示例中使用nodeDataframe.iloc[nodeIndices-startingId]where startingIdis 764525 并且nodeIndices是一个包含节点 ID(例如。elementDataframe['Node 1']此操作O(n)及时完成,应该比基本连接更快。更准确地说,在您的情况下,代码应如下所示:

nodeDataframe.iloc[elementDataframe['Node ID']-nodeDataframe['Node ID'].min()]

推荐阅读