【问题标题】:Finding if string has element from list and returning that element from list查找字符串是否具有列表中的元素并从列表中返回该元素
【发布时间】:2021-12-29 15:43:47
【问题描述】:

目前我正在努力寻找一种优雅的方式来解决我面临的问题。

我有一个大数据框,其中包含一个带有部门名称的列:

输入

demo = pd.DataFrame(
    {'Department':
        ['AA','AA1','BB team 1','AA but also a bit of nonsense',
        'BB','AA','department BB','Complete nonsense']}
    )
Department
AA
AA1
BB team 1
AA but also a bit of nonsense
BB
AA
department BB 
Complete nonsense

我还有一个已知部门的列表:

known_departments = ['AA','BB']

可以看出,列表中有三类部门:

  1. 与已知部门完全匹配的部门,应保持不变。
  2. 作为已知部门变体的部门。 即:它包含部门名称,但存在一些其他文本。这些应该映射到原始已知部门。
  3. 完整的废话部门,与已知部门没有任何匹配,这些也应该保持不变。

期望的输出

Department                      Department_simplified
AA                              AA
AA1                             AA
BB team 1                       BB
AA but also a bit of nonsense   AA
BB                              BB
AA                              AA
department BB                   BB
Complete nonsense               Complete nonsense

更新

感谢 Chris 和 sophocles 的回答。虽然使用 str.extractstr.findall 看起来更优雅,但在性能方面,apply+function 在我的实际 df 上都优于:

Solution    %%timeit -n20
Chris       1.65s ± 311 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
sophocles   1.14s ± 294 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
Paul        680 ms ± 174 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)

【问题讨论】:

  • 这能让你开始吗?也有一些矢量化的解决方案stackoverflow.com/questions/48590488/…
  • 我去看看,谢谢。
  • @CallumDA。这可行,但与我在下面的答案相同。我想我对矢量化解决方案更感兴趣。
  • 什么是统计数据?部门多久与部门简化相同?有多少部门?平均部门名称是多长,平均部门名称是多长时间?

标签: python pandas performance


【解决方案1】:

您可以在此处使用str.extract,并构建以|(或)分隔的部门列表作为模式。

import pandas as pd

known_departments = ['AA','BB']

demo = pd.DataFrame(
    {'Department':
        ['AA','AA1','BB team 1','AA but also a bit of nonsense',
        'BB','AA','department BB','Complete nonsense']}
    )

demo['Department_simplified'] = demo.Department.str.extract(f"({'|'.join(known_departments)})")

# If you need to fill nulls with the original dept name
demo['Department_simplified'].fillna(demo['Department'], inplace=True)

print(demo)

输出

    Department Department_simplified
0                             AA                    AA
1                            AA1                    AA
2                      BB team 1                    BB
3  AA but also a bit of nonsense                    AA
4                             BB                    BB
5                             AA                    AA
6                  department BB                    BB
7              Complete nonsense     Complete nonsense

【讨论】:

    【解决方案2】:

    您可以先使用str.findall 将您的部门列的匹配子字符串与您的列表元素 (known_departments) 返回。对于不返回任何内容的,您只需使用 Department 中的值,因为没有任何匹配项

    demo['Department_simplified'] = demo['Department']\
        .str.findall('|'.join(known_departments)).str.join('')
    
    demo['Department_simplified'] = np.where(
        demo['Department_simplified'].eq(''),demo['Department'],demo['Department_simplified'])
    

    打印:

                          Department Department_simplified
    0                             AA                    AA
    1                            AA1                    AA
    2                      BB team 1                    BB
    3  AA but also a bit of nonsense                    AA
    4                             BB                    BB
    5                             AA                    AA
    6                  department BB                    BB
    7              Complete nonsense     Complete nonsense
    

    【讨论】:

      【解决方案3】:

      我目前将 apply 与函数结合使用来获得我的结果。

      代码:

      def item_in_string(string, list_of_items):
          for item in list_of_items:
              if item in string:
                  return item
          return string
      
      demo['Department_simplified'] = demo.Department.apply(
          lambda x: item_in_string(x, known_departments) if isinstance(x, str) else x)
      

      不过,这样感觉效率不是很高,也不是pythonic。

      我想知道是否有人有更好的方法来解决这个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-17
        • 2019-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-19
        • 1970-01-01
        相关资源
        最近更新 更多