【问题标题】:Python - Count the number of exact matches between one list and multiple listsPython - 计算一个列表和多个列表之间的完全匹配数
【发布时间】:2018-12-01 20:15:51
【问题描述】:

首先,我有一个已转换为数据框 (df) 的 excel 文件(或 csv 文件)。

接下来,第一列中有一个字符串主列表,其中包含字母数字字符。

然后,在后续列中有字符串列表,可以是相同长度 (list1)、更短 (list2) 或更长 (list3)。

我想count(或summaster_list 与其他列表之间完全匹配的数量。


# Assign spreadsheet filename to `file`
file = "list_match.xlsx"

# Load spreadsheet
import pandas as pd
df = pd.read_excel(file)

print (df)
master_list list1   list2   list3
abc         abc     abc     stu
def         xxx     def     zzz
ghi         xxx     yyy     zzz
jkl         xxx     yyy     zzz
mno1        xxx     yz1     zzz
pqr         xxx             zzz
stu         xxx             zzz
vwx         xxx             zzz
yz1         xxx             zzz
yz2         xx1             zzz
yz3         xx1             zzz
                            zzz
                            mno1
                            zzz

目标是创建这个结果:

List     Count
list1    1
list2    3
list3    2

结果说明:

  • list1 中有一个匹配项:'abc'
  • list2 中有三个匹配项:'abc'、'def'、'yz1'
  • list3 中有两个匹配项:'stu'、'mno1'

我的问题类似于this question,除了数据被转置并且有多个列表需要比较,这可能需要循环。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    与:

       master_list list1 list2 list3
    0          abc   abc   abc   stu
    1          def   xxx   def   zzz
    2          ghi   xxx   yyy   zzz
    3          jkl   xxx   yyy   zzz
    4         mno1   xxx   yz1   zzz
    5          pqr   xxx   NaN   zzz
    6          stu   xxx   NaN   zzz
    7          vwx   xxx   NaN   zzz
    8          yz1   xxx   NaN   zzz
    9          yz2   xx1   NaN   zzz
    10         yz3   xx1   NaN   zzz
    11         NaN   NaN   NaN   zzz
    12         NaN   NaN   NaN  mno1
    13         NaN   NaN   NaN   zzz
    

    使用df.applynp.isin

    df.apply(lambda col:np.isin(col,df.master_list).sum())
    and 
    

    df.isin:

    df.isin(df.master_list.dropna().tolist()).sum()
    

    结果:

    master_list    11
    list1           1
    list2           3
    list3           2
    dtype: int64
    

    【讨论】:

    • 为了获得更多洞察力,在较大的数据帧上首选这些解决方案之一。我需要实际帮助的数据框要大得多—— 10 列和数千行......请注意在更大的数据框上运行两段代码所需的时间差异。使用 df.applynp.isin 需要 55.95 秒。使用 df.isin 需要 0.83 秒。
    • 是的! .我知道。 df.isin 使用快速索引技术。漂亮的解释在这里:stackoverflow.com/questions/50779617/…
    【解决方案2】:

    创建主列表的非空值列表并使用dataframe.isin

    master_list = df.loc[df['master_list'].notnull(), 'master_list'].tolist()
    df.iloc[:, 1:].isin(master_list).sum()
    
    
    
    list1    1
    list2    3
    list3    2
    

    【讨论】:

    • 不幸的是,这并没有提供正确的解决方案。 list1 4, list2 12, list3 2
    • 此解决方案有效。我将接受并给不同的答案打勾,因为它只使用一行代码而不是两行,但这个代码当然可以使用。
    • 为了进一步了解,我需要实际帮助的数据框要大得多——10 列和数千行。您的代码在更大的数据帧上运行需要 0.90 秒,仅比 @B.M. 提供的代码长。
    【解决方案3】:

    使用numpy广播

    s1=df.iloc[:,1:].values
    s2=df['master_list'].values[:,None]
    np.sum(s1==s2[:,None],1).sum(0)
    Out[409]: array([1, 3, 2])
    

    【讨论】:

    • 此代码适用于我的示例中的数据框。我需要实际帮助的数据框要大得多——10 列和数千行。当我尝试在更大的数据帧上运行您的代码时,我收到以下错误:numpy.core._internal.AxisError: axis 1 is out of bounds for array of dimension 0
    【解决方案4】:

    你可以在用NaN替换空字符串后使用df.isin

    df.replace(r'^\s*$', 'NaN', regex=True).isin(df.master_list.values).sum()
    

    这会计算所有出现在列df.master_list 中的df 元素。请注意,[sum()][1] 默认情况下沿 0 轴(按列),默认情况下会跳过 null/NaN 值,因此这与以下内容相同:

    df.replace(r'^\s*$', 'NaN', regex=True).isin(df.master_list.values).sum(axis=0, skipna=True)
    

    例子:

    >>> df
      list1 list2 master_list
    0   abc   stu         abc
    1   yyy   xxx         def
    2         xxx
    3         xxx
    4         xxx
    >>> df.replace(r'^\s*$', 'NaN', regex=True).isin(df.master_list.values).sum()
    list1          1
    list2          0
    master_list    2
    dtype: int64
    

    【讨论】:

    • 这将首先匹配索引和值。
    • 不幸的是,这并没有提供正确的解决方案。 master_list 14, list1 4, list2 12, list3 2 ...我认为问题在于,当没有空格 (NaN) 并且列的长度相同时,您的解决方案可以完美运行...master_list 有 11 行,但master_list 14 以上的结果让我觉得它反映了最长列表的长度list3
    • 我在运行这段代码时得到了相同的结果。可能差异是因为我的示例中的数据框是从 excel 文件创建的?
    • @milaske 也许您应该在示例中发布 Excel 文件
    • 这是个好建议。我搜索了帮助中心以及如何“如何提出一个好问题?”看看是否可以发布 excel 文件。不幸的是,我无法找到如何做到这一点。由于此问题的其他答案正常,因此可能没有必要。
    猜你喜欢
    • 2017-04-21
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多