【问题标题】:Simplifying a list into categories将列表简化为类别
【发布时间】:2017-09-15 02:39:40
【问题描述】:

我是一名新的 Python 开发人员,想知道是否有人可以帮助我解决这个问题。我有一个数据集,其中有一列描述公司类型。我注意到该列列出了例如手术、手术。它列出了眼镜、眼镜和验光。因此,我不想在本专栏中有一个庞大的列表,我只想简单地说明如果你找到一个包含“eye”、“glasses”或“opto”的词,那么只需将其更改为“eyewear”。我的初始代码如下所示:

def map_company(row):
    company = row['SIC_Desc']
    if company in 'Surgical':
         return 'Surgical'
    elif company in ['Eye', 'glasses', 'opthal', 'spectacles', 'optometers']:
        return 'Eyewear'
    elif company in ['Cotton', 'Bandages', 'gauze', 'tape']:
        return 'First Aid'
    elif company in ['Dental', 'Denture']:
        return 'Dental'
    elif company in ['Wheelchairs', 'Walkers', 'braces', 'crutches', 'ortho']:
        return 'Mobility equipments'
    else:
        return 'Other'

df['SIC_Desc'] = df.apply(map_company,axis=1)

这是不正确的,因为它将每个项目都更改为“其他”,所以很明显我的语法是错误的。有人可以帮我简化我试图重新标记的这个列吗? 谢谢

【问题讨论】:

  • 已经验证了进入company的值?
  • 为什么不直接使用调试器呢?调试器是你的朋友,抓住机会学习使用调试器!
  • 你也可以发布你正在使用的数据集吗?
  • 听起来你的病情倒退了。你想要'Dental' in company。您可以使用any() 来获得比较多个值的预期效果,例如:elif any(i in company for i in ['Dental', 'Denture']): ...
  • 你好 Champion 你能扩展你的代码吗?它似乎不起作用。这就是我所拥有的: def map_company(row): company = row['SIC_Desc'] if any(i in company for i in ['Surgical', 'Surgery']): return 'Surgical' elif any(i in company for i in ['Eye', 'glasses', 'opthal', 'spectacles', 'optometers']): return 'Eyewear' elif any(i in company for i in ['Cotton', 'Bandages', 'gauze'] ', 'tape']): return 'First Aid' else: return 'Other' df['SIC_Desc'] = df.apply(map_company,axis=1)

标签: python


【解决方案1】:

如果没有数据集的确切内容,很难回答,但我可以看到一个错误。根据您的描述,您似乎看错了。您希望其中一个词出现在您的公司描述中,因此应该如下所示:

if any(test in company for test in ['Eye', 'glasses', 'opthal', 'spectacles', 'optometers'])

但是您可能在这里遇到案例问题,所以我建议您:

company = row['SIC_Desc'].lower()
if any(test.lower() in company for test in ['Eye', 'glasses', 'opthal', 'spectacles', 'optometers']):
    return 'Eyewear'

您还需要确保 company 是一个字符串,并且 'SIC_Desc' 是一个正确的列名。

最后你的函数会是这样的:

def is_match(company,names):
    return any(name in company for name in names)

def map_company(row):
    company = row['SIC_Desc'].lower()
    if 'surgical' in company:
         return 'Surgical'
    elif is_match(company,['eye','glasses','opthal','spectacles','optometers']):
        return 'Eyewear'
    elif is_match(company,['cotton', 'bandages', 'gauze', 'tape']):
        return 'First Aid'
    else:
        return 'Other'

【讨论】:

  • @Chinny84 哦,确实!感谢您注意到这一点。编辑:我修复了它
  • 那么你会通过编写 df['SIC_Desc'] = df.apply(map_company,axis=1) 来完成代码吗?我已经尝试过了,它仍然将所有行列为“其他”
【解决方案2】:

这是一个使用 reversed dictionary 的选项。

代码

import pandas as pd


# Sample DataFrame
s = pd.Series(["gauze", "opthal", "tape", "surgical", "eye", "spectacles", 
               "glasses",  "optometers", "bandages", "cotton", "glue"])
df = pd.DataFrame({"SIC_Desc": s})
df

LOOKUP = {
    "Eyewear": ["eye", "glasses", "opthal", "spectacles", "optometers"],
    "First Aid": ["cotton", "bandages", "gauze", "tape"],
    "Surgical": ["surgical"],
    "Dental": ["dental", "denture"],
    "Mobility": ["wheelchairs", "walkers", "braces", "crutches", "ortho"],
}

REVERSE_LOOKUP = {v:k for k, lst in LOOKUP.items() for v in lst}

def map_company(row):
    company = row["SIC_Desc"].lower()
    return REVERSE_LOOKUP.get(company, "Other")


df["SIC_Desc"] = df.apply(map_company, axis=1)
df


详情

我们定义了一个LOOKUP 字典,其中分别包含预期输出和相关单词的(键、值)对。请注意,这些值是小写的以简化搜索。然后我们使用反向字典来自动反转键值对,提高搜索性能,例如:

>>> REVERSE_LOOKUP
{'bandages': 'First Aid',
 'cotton': 'First Aid',
 'eye': 'Eyewear',
 'gauze': 'First Aid',
 ...}

请注意,这些参考字典是在映射函数之外创建的,以避免为每次调用 map_company() 重新构建字典。最后,映射函数通过调用.get(),使用反向字典快速返回所需的输出,如果没有找到条目,该方法将返回默认参数"Other"

请参阅 @Flynsee 的有见地的回答,了解代码中发生的情况。与一堆条件语句相比,代码更简洁。

好处

由于我们使用了字典,因此搜索时间应该相对较快,O(1) 与使用 in 的 O(n) 复杂度相比。此外,主要的 LOOKUP 字典具有适应性,并且可以从手动为新条目执行大量条件语句中解放出来。

【讨论】:

    猜你喜欢
    • 2018-10-06
    • 2016-11-05
    • 1970-01-01
    • 2016-05-21
    • 2010-09-15
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多