【问题标题】:Loop and arrays of strings in pythonpython中的循环和字符串数组
【发布时间】:2019-03-17 07:53:37
【问题描述】:

我有以下数据集:

column1

HL111
PG3939HL11
HL339PG
RC--HL--PG

我正在尝试编写一个执行以下操作的函数:

  1. 循环遍历 column1 的每一行
  2. 只提取字母并放入数组中
  3. 如果数组中包含“HL”,请将其从数组中删除,除非 HL 是数组中唯一的单词。
  4. 取数组中的第一个单词并输出结果。

所以对于上面的例子,我的数组(step2)看起来像这样:

[HL]
[PG,HL]
[HL,PG]
[RC,HL,PG]

我想要的最终输出(第 4 步)如下所示:

desired_column

HL
PG
PG
RC

我有第 2 步的代码,它似乎工作正常

df['array_column'] = (df.column1.str.extractall('([A-Z]+)')
                    .unstack()
                    .values.tolist())

但我不知道如何从这里到达我的最终输出(步骤 4)。

【问题讨论】:

  • 如果单元格没有字母,你会期待什么? !!!!!11111?
  • 如果单元格没有字母,则结果可以为空或为空
  • 我添加了an answer,它处理没有字母的单元格并遵循您的初始逻辑。

标签: python arrays regex pandas loops


【解决方案1】:

您可以先替换所有非字母,然后提取成对的字母,然后应用一些自定义逻辑从数组中提取必要的值来实现您的需要:

>>> df['array_column'].str.replace('[^A-Z]+', '').str.findall('([A-Z]{2})').apply(lambda d: [''] if len(d) == 0 else d).apply(lambda x: 'HL' if len(x) == 1 and x[0] == 'HL' else [m for m in x if m != 'HL'][0])
0    HL
1    PG
2    PG
3    RC
Name: array_column, dtype: object
>>> 

详情

  • .replace('[^A-Z]+', '') - 删除除大写字母以外的所有字符
  • .str.findall('([A-Z]{2})') - 提取字母对
  • .apply(lambda d: [''] if len(d) == 0 else d) 会在上一步没有正则匹配的情况下添加一个空项
  • .apply(lambda x: 'HL' if len(x) == 1 and x[0] == 'HL' else [m for m in x if m != 'HL'][0]) - 自定义逻辑:如果列表长度为 1 且等于 HL,则保留它,否则删除所有 HL 并获取第一个元素

【讨论】:

    【解决方案2】:

    这是使用apply的一种方法

    演示:

    import re
    import pandas as pd
    
    def checkValue(value):
        value = re.findall(r"[A-Z]{2}", value)
        if (len(value) > 1) and ("HL" in value):
            return [i for i in value if i != "HL"][0]
        else:
            return value[0]    
    
    df = pd.DataFrame({"column1": ["HL111", "PG3939HL11", "HL339PG", "RC--HL--PG"]})
    print(df.column1.apply(checkValue))
    

    输出:

    0    HL
    1    PG
    2    PG
    3    RC
    Name: column1, dtype: object
    

    【讨论】:

      【解决方案3】:

      你可以做这样的事情(或者可能更优雅的事情),你已经得到了一个相当不错的结构,你可以使用 groupby 来完成你的解决方案

      def extract_relevant_str(grp):
          ret_val = None
          if "HL" in grp[0].tolist() and len(grp) == 1:
              ret_val = "HL"
          elif len(grp) >= 1:
              ret_val = grp.loc[grp[0] != "HL", 0].iloc[0]
          return ret_val
      
      items = df.column1.str.extractall('([A-Z]+)')
      items.reset_index().groupby("level_0").apply(extract_relevant_str)
      

      输出:

      level_0
      0    HL
      1    PG
      2    PG
      3    RC
      dtype: object
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-13
        • 1970-01-01
        • 1970-01-01
        • 2012-05-25
        相关资源
        最近更新 更多