在 python 中:如何在同一行中找到匹配的字符串,将(模糊)匹配的字符串的一部分与列表进行比较?

In python: How to find match of string in same row, compare part of (fuzzy) matched string to list?

我有一个匹配问题,我已尝试解决,但还没有找到解决方法。我是 python 的新手,所以可能有一些简单的方法可以做到这一点。我搜索了这些问题,但没有找到任何能完全满足我需要的东西。

目的

我需要确定 "type" 个人(将在下面定义),如果他们属于一组列表中的一个,请记下该组。结果应该是数据框中的一行,其中包含对人员姓名、类型和从属关系的观察。数据都以字符串形式存在,并且我必须解析出字符串的多个部分。

数据

我的数据目前是这样的:

lastname       person1                person2                person3
smith          matt smith, company a  tom jones, company b   karen cook, company c
jones          matt smith, company a  tom jones, company b   karen cook, company c
cook           matt smith, company a  tom jones, company b   karen cook, company c

另外,我有一个公司列表

CompanyName
company a
company b
company d

对于数据帧中的每一行,这些步骤粗略地(在伪代码中)

If lastname is in person1:
   if person1 company is in list of CompanyNames:
       df['persontype'] = 1 #where 1 indicates being in a listed company
       df['affiliation'] = company name #the matched item from CompanyName list
   else if lastname is in person2: 
       if person2 company is in list of CompanyNames: 
            df['personatype'] = 1
            df['affiliation'] = company name
       else if lastname is in person3: 
            if person3 company name is in list of CompanyNames: 
                df['persontype'] = 1
                df['affiliation'] = company name
            else: 
                df['persontype'] = 0 #indicating a person in an unlisted company
                df['affiliation'] = 'Unlisted'

我知道这读起来很糟糕,但我才刚刚开始。 (欢迎所有评论。)

问题是:

  1. 姓氏很短,因此与人员列表的匹配可以很简单 is 'a' in 'b',但我希望 person1...N 字符串中的公司名称有拼写错误或特质(想想 "C-SPAN" 和 "CSPAN" 作为一个名字的可能版本)。
  2. 人员的列数是静态的。也就是说,它是固定的(尽管许多条目将为空,因此虽然列数固定为 100,但某些行将只有 1 或 2 个条目)。
  3. person1...N 字符串的格式不一致。也就是说,可能有多个逗号、句点、连字符等。因此,在逗号 a 之后拆分并获取所有内容并不总是会给出公司名称。

更新

多亏了很多问题,我意识到我对数据格式的了解还不够详细。 person1..N 列下的条目变化很大。以下这些列中的实际数据示例:

person1
Hill, Daniel O., Assistant Administrator for Technology, U.S. Small Business Administration
person2
R&D Credit Coalition, R. Randall Capps

这就是为什么我没有立即尝试使用 .split() 方法的原因。 token的顺序不统一,有的还有position/job以及组织名称,名称并不总是"phone book"顺序。

期望的结果

我想要结束的是一个数据框(除了所有其他列)

lastname  ...   persontype     affiliation 
smith           1              company a
jones           1              company b
cook            0              None

非常感谢您对此提出的任何指示、指导等。我一直在使用 fuzzywuzzy 模块,但没有取得任何成功。

注意:我没有在此处提供示例代码,因为失败不是单行或函数。我提供的任何内容都会有太多的附属问题,不值得您花时间研究。

数据格式

提供的数据格式对关联或定界符不清楚,所以我要重申我认为你的意思。 (在 python 句法结构中)

您的数据:

lastname       person1                person2                person3
smith          matt smith, company a  tom jones, company b   karen cook, company c
jones          matt smith, company a  tom jones, company b   karen cook, company c
cook           matt smith, company a  tom jones, company b   karen cook, company c

另外,我有一个公司列表

CompanyName
company a
company b
company d

我认为是什么意思:

lastname = ['smith','jones','cook']
companies = ['company a','company b']
affiliations = {'matt smith':'company a','tom jones':'company b','karen cook':'company c'}

我觉得应该怎么格式化

lastname = ['smith','jones','cook']
companies = ['company a','company b']
names = {'smith':'matt smith','jones':'tom jones','cook':'karen cook'}
affiliations = {'matt smith':'company a','tom jones':'company b','karen cook':'company c'}

想要的结果

想法是提供以下输出:

lastname  ...   persontype     affiliation 
smith           1              company a
jones           1              company b
cook            0              None

如何得到想要的结果

注意:这是使用我认为最好的格式。

print('lastname\tpersontype\taffiliation\n')
for last in lastname:
    if last in names:
        full = names[last]
        if full in affiliations:
            comp = affiliations[full]
            if comp in companies:
                print(full+'\t1\t'+comp)
            else:
                print(full+'\t0\tNone')
        else:
            print(full+' is not listed in affiliations.')
    else:
        print(last+' has no matches in names.')
    print('\n')

我不知道您是否能够创建我认为您应该使用的数据格式。尽管如果您的数据是具有您提供的形状的纯文本格式,那么读取文件和处理行应该相当简单。

如果您想将其打印回文件,这也是可行的,请研究内置函数 open() 和 write()。

希望对您有所帮助。享受吧!