将列表与DataFrame中的每个记录进行比较 - python

我有一个用例,其中我将同一列中的列表与其自身进行比较,代码如下:

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 for循环),并且花费大量时间来进行操作。
其背后的主要思想是链接记录,其中counts95 ['links']中的列表中的元素位于任何后续行中,如果是,则仅当linksoflinks列为None(不覆盖)时,才用第一列的索引更新linkslinks列)

找到下面的参考表:

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

python参考方案

所需的输出使用与示例数据框构造函数相比不同的值和列名。我使用您所需的输出数据框进行测试。

逻辑:
对于links的每个子列表,我们需要找到第一个重叠子列表的行索引(我是指数据帧的索引,不是列index)。我们将使用这些行索引对.loc上的counts95进行切片,以获取列index的相应值。为了实现此目标,我们需要执行几个步骤:

将每个子列表与link中的所有子列表进行比较。列表理解为
快速高效地完成此任务。我们需要编写清单
理解创建布尔2D掩码数组,其中每个子数组
包含重叠行的True值和非重叠行的False(请参阅本指南的逐步说明)
2D遮罩并检查列links,您会看到更清晰的图像)
我们要从顶部到当前子列表进行比较。即常设
从当前行开始,我们只想向后进行比较。
因此,我们需要将任何正向比较设置为False。这是
np.tril的功能
在此2D蒙版的每个子数组中,True的位置/索引为
当前子列表重叠的行的行索引。我们需要找到
True的这些位置。它是np.argmax的功能。
np.argmax返回数组的第一个max元素的位置/索引。 True被视为1False被视为0。因此,
在具有True的任何子数组上,它正确返回第一个重叠的行索引。但是,在所有False子数组上,它返回0。我们稍后将使用False处理所有where子数组
np.argmax之后,将2D蒙版缩小为1D蒙版。每个元素
此一维掩码是重叠子列表的行索引数。
将其传递给.loc以获取列index的相应值。
但是,结果也错误地包含了其中的子数组所在的行
2D掩码包含所有False。我们希望这些行转到NaN。它是
.where的功能

方法1:
使用列表推导在m的每个列表和links中的所有列表之间构造布尔2D掩码links。我们只需要向后比较,因此使用np.tril将蒙版的右上角压碎为代表正向比较的所有False。最后,调用np.argmax以获得第一个Truem的每一行中的位置,并链接whereFalse的所有m行变为NaN

c95_list = counts95.links.tolist()
m = np.tril([[any(x in l2 for x in l1) for l2 in c95_list] for l1 in c95_list],-1)
counts95['linkoflist'] = (counts95.loc[np.argmax(m, axis=1), 'index']
                                  .where(m.any(1)).to_numpy())

 Out[351]:
     index  level0            links  linkoflist
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

方法2:
如果您的数据帧很大,则将每个子列表与links的顶部进行比较可以使其更快。在大数据帧上,方法1可能快2倍。

c95_list = counts95.links.tolist()
m = [[any(x in l2 for x in l1) for l2 in c95_list[:i]] for i,l1 in enumerate(c95_list)]
counts95['linkoflist'] = counts95.reindex([np.argmax(y) if any(y) else np.nan 
                                                   for y in m])['index'].to_numpy()

循序渐进(方法1)

m = np.tril([[any(x in l2 for x in l1) for l2 in c95_list] for l1 in c95_list],-1)

Out[353]:
array([[False, False, False, False, False, False],
       [ True, False, False, False, False, False],
       [ True, False, False, False, False, False],
       [False, False, False, False, False, False],
       [ True, False,  True,  True, False, False],
       [ True, False,  True,  True,  True, False]])

argmax返回所有True行的第一False和第一False位置。

In [354]: np.argmax(m, axis=1)
Out[354]: array([0, 0, 0, 0, 0, 0], dtype=int64)

使用argmax的结果进行切片

counts95.loc[np.argmax(m, axis=1), 'index']

Out[355]:
0    616351
0    616351
0    616351
0    616351
0    616351
0    616351
Name: index, dtype: int64

链接where将与所有False对应的行从m转换为NaN

counts95.loc[np.argmax(m, axis=1), 'index'].where(m.any(1))

Out[356]:
0         NaN
0    616351.0
0    616351.0
0         NaN
0    616351.0
0    616351.0
Name: index, dtype: float64

最后,输出的索引不同于counts95的索引,因此只需调用to_numpy即可将ndarray分配给linkoflist的列counts95

Python pytz时区函数返回的时区为9分钟 - python

由于某些原因,我无法从以下代码中找出原因:>>> from pytz import timezone >>> timezone('America/Chicago') 我得到:<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD…

用大写字母拆分字符串,但忽略AAA Python Regex - python

我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…

Python:同时在for循环中添加到列表列表 - python

我想用for循环外的0索引值创建一个新列表,然后使用for循环添加到相同的列表。我的玩具示例是:import random data = ['t1', 't2', 't3'] masterlist = [['col1', 'animal1', 'an…

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

查找字符串中的行数 - python

我正在创建一个python电影播放器​​/制作器,我想在多行字符串中找到行数。我想知道是否有任何内置函数或可以编写代码的函数来做到这一点:x = """ line1 line2 """ getLines(x) python大神给出的解决方案 如果换行符是'\n',则nlines …