pandas 基于匹配列的子字符串提取

ezykj2lf  于 2023-04-28  发布在  其他
关注(0)|答案(1)|浏览(135)

我需要一个代码,做2个功能。更新我添加了一些我忘记的要求
1,如果在列表中找到子字符串,则应该用名称标记它,例如,如果找到“0325”,则在另一列中添加“animal_customer”,如果没有找到匹配项,则应该在本例中命名为“speces”的列中注明“unknown”
2,如果找到子字符串,那么,在另一个具有长字符串的列上,它应该向左提取1个子字符串(空格分隔),向右提取3个子字符串(也是空格分隔)。之后,如果找到并添加到另一列,则该列(在本例中命名为story)不是必需的。注意,如果在步骤1中没有匹配,那么该列应该说“I.D. not found”
3,有一个机会,超过1个标签将发生,我需要所有这些显示为列中的列表
下面是列表的一个示例,以及初始表和结果表的外观

animal = ["0325", "9985"]

human = ["9984", "1859"]

原表-〉
| 名称|种id|故事|
| --------------|--------------|--------------|
| 鲍勃|010199840101|根据研究,人类来自美国或附近|
| 菲多|010199850101|根据研究,动物来自台湾或附近|
| 外星人|010145660101|根据研究E.T.来自火星或附近|
| 人熊Pig|03259984010101|根据研究,人类来自火星或附近,动物也可能是外星人。|
结果表-〉
| 名称|种id|种|原始表|萃取物|
| --------------|--------------|--------------|--------------|--------------|
| 鲍勃|010199840101|人类顾客|人|研究,人类来自美国。|
| 菲多|010199850101|动物消费者|动物|研究,动物来自台湾|
| 外星人|010145660101|未知的|无|未找到ID|
| 人熊Pig|03259984010101|“human_customer”,“animal_customer”|“动物”,“人类”|“研究,人类来自火星”,“动物可能是外星人”|
我试图解决这个问题:

animal_df = df[df["species_id"].str.contains('|'.join(map(re.escape, animal)))]
animal_df["specie"] = "animal_customer"

human_df = df[df["species_id"].str.contains('|'.join(map(re.escape, human)))]

human_df["specie"] = "human_customer"

df_append = pd.concat(["human_df", "animal_df"])

问题:
正如您所看到的,我的尝试将识别并标记该行,就好像它包含动物或人一样,但如果它不匹配任何内容,则不会显示错误,并且还将添加重复项。

hivapdat

hivapdat1#

我会使用正则表达式来实现这一点。首先你需要找到任何标识一个物种的值。这可以用create_pattern函数来完成,该函数返回一个带有命名组的正则表达式模式。为了简单起见,我把所有物种Map都放在species_mapping字典下,这里的键代表了你想要放入df中的值。然后所有的模式将简单地用管道连接起来,创建正则表达式species_patternmap_species函数只是返回最先找到的正则表达式组或“unknown”。最后一步是将此函数Map到列species_id并将其存储在species列中。

import pandas as pd
import re

def create_pattern(name: str, values: list):
    return rf"(?P<{name}>{'|'.join(values)})"

df = pd.DataFrame(
    {
        "name": ["Bob", "Fido", "E.T.", "ManBearPig"],
        "species_id": ['010199840101', '010199850101', '010145660101', '03259984010101']
    }
)

species_mapping = {
    "animal_customer": ["0325", "9985"],
    "human_customer": ["9984", "1859"],
}

joined_patterns = "|".join(create_pattern(name, values) for name, values in species_mapping.items())
species_pattern = re.compile(rf"({joined_patterns})+")
# will be like '((?P<animal_customer>0325|9985)|(?P<human_customer>9984|1859))+'

def map_species(species_id):
    m = species_pattern.search(species_id)
    if not m:
        return "unknown"
    return ",".join(group for group, value in m.groupdict().items() if value is not None)

df["species"] = df["species_id"].map(map_species)

print(df.to_string())

>>>           name      species_id                         species
>>>  0         Bob    010199840101                  human_customer
>>>  1        Fido    010199850101                 animal_customer
>>>  2        E.T.    010145660101                         unknown
>>>  3  ManBearPig  03259984010101  animal_customer, human_customer

我将以类似的方式处理第二项任务。

相关问题