我有一个用例,将同一列中的列表与其自身进行比较,代码如下:
for i in range(0,len(counts95)):
for j in range(i+1,len(counts95)):
for x in counts95['links'][i]:
for y in counts95['links'][j]:
if x == y and counts95['linkoflinks'][j] is None:
counts95['linkoflinks'][j] = counts95['index'][i]
代码可以工作,但对python不友好(使用4表示循环),并且需要花费大量的时间来执行操作。 它背后的主要思想是将列表中95['links']列中的元素位于任何一行的记录链接起来,如果是,则仅当linksoflinks列为None(无覆盖)时,才使用第一列的索引更新列linksoflinks
请参阅下面的参考表:
counts95 = pd.DataFrame({'index': [616351, 616352, 616353,6457754],
'level0': [25,30,35,100],
'links' : [[1,2,3,4,5],[23,45,2],[1,19,67],[14,15,16]],
'linksoflinks' : [None,None,None,None]})
编辑: 新数据帧
counts95 = pd.DataFrame({'index': [616351, 616352, 616353,6457754,6566666,464664683],
'level0': [25,30,35,100,200,556],
'links' : [[1,2,3,4,5],[23,45,2],[1,19,67],[14,15,16],[1,14],[14,1]],
'linksoflinks' : [None,None,None,None,None,None]})
期望输出:
index level0 links linksoflinks
0 616351 25 [1, 2, 3, 4, 5] NaN
1 616352 30 [23, 45, 2] 616351.0
2 616353 35 [1, 19, 67] 616351.0
3 6457754 100 [14, 15, 16] NaN
4 6566666 200 [1,14] 616351.0
5 6457754 556 [14,1] 616351.0
使用
explode
和duplicated
和.map
分配给重复的链接值,但只分配后者好的模式是为您的任务使用适当的数据结构。回答问题«Y序列中是否存在元素X»的最佳选择是内置的
set
。当您的集合是不可变的时,考虑使用^ {CD2}}。解决方案
以下是我将如何以pythonic的方式解决这个问题:
链接的内容链接的内容:
defaultdict(<class 'list'>, {616351: [616352, 616353]})
复杂性
现在让我们比较一下您的解决方案和我的解决方案的复杂性,以证明后者更有效。让我们假设}
N
是行数L
是链接列表的某种长度(平均值或最大值,这并不重要)。您的解决方案大致比较了所有行对,这给了我们O(N * N)
。然后乘以两个列表的简单比较的复杂性-O(L * L)
。它总共给了我们{建议的解决方案仍然交叉连接所有行,因此
N * N
与我们同在。但是现在我们用一种更有效的方式来比较集合本身:O(min(L, L)) === O(L)
,正如Python Time Complexity所说。因此,总体复杂性除以单个L
,将O(N² * L)
作为总数与示例dataframe构造函数相比,所需的输出使用不同的值和列名。我使用您想要的输出数据帧进行测试
逻辑:
对于
links
的每个子列表,我们需要找到第一个重叠子列表的行索引(我指的是数据帧的索引,而不是列index
)。我们将使用这些行索引在counts95
上按.loc
切片,以获得列index
的相应值。为了实现这一目标,我们需要采取以下几个步骤:link
中的所有子列表进行比较。列表理解是 快速有效地完成这项任务。我们需要编写一份清单 理解如何创建布尔二维掩码数组,其中每个子数组 包含重叠行的True
值和非重叠行的False
值(请参阅本指南的分步说明) 2D遮罩并检查列links
您将看到更清晰的内容)False
相比的任何前向。这是 {True
的位置/索引是 当前子列表重叠的行的行索引。我们需要找到 这些位置是True
。它是np.argmax
的功能。np.argmax
返回数组的第一个max元素的位置/索引True
被认为是{True
的任何子数组上,它正确返回第一个重叠行索引。但是,在所有False
子数组上,它返回0
。稍后我们将使用where
处理所有False
子阵列np.argmax
之后,2D掩码被缩减为1D掩码。每个元素 此1D掩码是重叠子列表的行索引数。 将其传递给.loc
以获取列index
的相应值。 然而,结果也错误地包括了 二维掩码包含所有False
。我们希望这些行变成NaN
。它是 {方法1:
使用列表理解在
links
的每个列表和links
中的所有列表之间构建布尔二维掩码m
。我们只需要向后比较,所以使用np.tril
将掩码的右上角三角形压碎为表示向前比较的所有False
。最后,调用np.argmax
以获取m
的每一行中第一个True
的位置,并链接where
以将m
的所有False
行转换为NaN
方法2:
如果dataframe很大,则将每个子列表仅与
links
的顶部进行比较会更快。在大数据帧上,它可能比方法1快2倍逐步(方法1)
argmax
返回所有False
行的第一个True
和第一个False
位置使用
argmax
的结果进行切片链
where
以将所有False
对应的行从m
转到NaN
最后,输出的索引不同于
counts95
的索引,因此只需调用to_numpy
即可获得要分配给counts95
的linkoflist
列的数据数组相关问题 更多 >
编程相关推荐