【问题标题】:Counting length of intersection of a list with pandas column of lists计算列表与熊猫列表的交集长度
【发布时间】:2020-02-26 19:19:35
【问题描述】:

我有一个唯一随机整数列表和一个包含一列列表的数据框,如下所示:

>>> panel
    [1, 10, 9, 5, 6]

>>> df
       col1 
    0  [1, 5]
    1  [2, 3, 4]
    2  [9, 10, 6]

我想要的输出是panel 和数据框中每个单独列表之间的重叠长度:

>>> result
       col1        res
    0  [1, 5]      2
    1  [2, 3, 4]   0
    2  [9, 10, 6]  3

目前,我正在使用apply 函数,但我想知道是否有更快的方法,因为我需要创建很多面板并为每个面板循环执行此任务。

# My version right now
def cntOverlap(panel, series):
    # Typically the lists inside df will be much shorter than panel, 
    # so I think the fastest way would be converting the panel into a set 
    # and loop through the lists within the dataframe

    return sum(1 if x in panel for x in series)
    #return len(np.setxor1d(list(panel), series))
    #return len(panel.difference(series))


for i, panel in enumerate(list_of_panels):
    panel = set(panel)
    df[f"panel_{i}"] = df["col1"].apply(lambda x: cntOverlap(panel, x))

【问题讨论】:

    标签: python pandas numpy intersection set-intersection


    【解决方案1】:

    由于每行的数据长度可变,我们需要在 Python 中进行迭代(显式或隐式,即幕后)。但是,我们可以优化到每次迭代计算最小化的水平。遵循这种理念,这里有一个带有数组分配和一些掩码的 -

    # l is input list of unique random integers
    s = df.col1
    max_num = 10 # max number in df, if not known use : max(max(s))
    map_ar = np.zeros(max_num+1, dtype=bool)
    map_ar[l] = 1
    df['res'] = [map_ar[v].sum() for v in s]
    

    或者使用 2D 数组分配来进一步最小化每次迭代计算 -

    map_ar = np.zeros((len(df),max_num+1), dtype=bool)
    map_ar[:,l] = 1
    for i,v in enumerate(s):
        map_ar[i,v] = 0
    df['res'] = len(l)-map_ar.sum(1)
    

    【讨论】:

    • 它可以按我的意愿工作,但是由于 numpy 数组中的内存分配,二维数组的优化对我不起作用。无论如何谢谢你!
    • 我现在才意识到max(max(s))不会返回列表列中最大的元素,这不是这一行的目的吗?我不得不把它改成max(s.apply(lambda x: max(x))
    【解决方案2】:

    您可以使用explode(可从pandas 0.25+ 获得)和isin

    df['col1'].explode().isin(panel).sum(level=0)
    

    输出:

    0    2.0
    1    0.0
    2    3.0
    Name: col1, dtype: float64
    

    【讨论】:

      猜你喜欢
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多