【问题标题】:Python: Validate if column entries match a desired formatPython:验证列条目是否与所需格式匹配
【发布时间】:2020-11-02 10:48:56
【问题描述】:

我目前正在运行健全性检查以验证 id 是否与所需格式匹配。我想为不符合所需标准格式的项目过滤我的数据框。 在这种情况下:

  • 前两个必须是字母
  • 总长度应为 16 个字符

我想找到任何不符合上述条件的项目。

>>> data = [['US-T-2018-08-110','Forward'],['EU-U-2001-04-019','Backward'],['EU-U-2017-05-178','Still'], ['N/A','Up'],['DE-T-1999-08-8512','Down']]
>>> df = pd.DataFrame(data, columns = ['project_id', 'name']) 
>>> df

project_id         name
US-T-2018-08-110   Forward
EU-U-2001-04-019   Backward
EU-U-2017-05-178   Still
N/A                Up
DE-T-1999-08-8512  Down

应该导致:

project_id         name
N/A                Up
DE-T-1999-08-8512  Down

此外,有没有办法在不循环的情况下实现这一点?

【问题讨论】:

  • 总长度到底是多少?没有一个字符串有 14 个字符
  • @DaniMesejo 嘿抱歉,忘记包含第一个字母 - 长度应为 16 - 已更正

标签: python python-3.x pandas numpy lambda


【解决方案1】:

使用boolean indexing,如下所示:

mask = ~df['project_id'].str.match("^[a-zA-Z]{2}") | df['project_id'].str.len().ne(16)
print(df[mask])

输出

          project_id  name
3                N/A    Up
4  DE-T-1999-08-8512  Down

str.match 函数执行以下操作,来自文档:

判断每个字符串是否以匹配正则表达式开头。

然后正则表达式模式^[a-zA-Z]{2} 检查字符串的前两个字符是否为字母。

【讨论】:

    【解决方案2】:

    我认为你需要Series.str.len 来获取长度,Series.str.contains 来测试前两个值是否是正则表达式^ 用于字符串开头的字母,[a-aA-Z] 字母和{2} 用于长度2:

    m = (df['project_id'].str.len().ne(16) | 
         ~df['project_id'].str.contains('^[a-zA-Z]{2}', na=False))
    df = df[m]
    print (df)
              project_id  name
    3                N/A    Up
    4  DE-T-1999-08-8512  Down
    

    什么像倒置面具一样工作:

    m1 = (df['project_id'].str.len().eq(16) & 
          df['project_id'].str.contains('^[a-zA-Z]{2}', na=False))
    df = df[~m1]
    print (df)
              project_id  name
    3                N/A    Up
    4  DE-T-1999-08-8512  Down
    

    感谢@Jon Clements 改进解决方案以检查前 2 个字母之后是否有下一个 14 值:

    df = df[~df['project_id'].str.match('[a-zA-Z]{2}.{14}$', na=False)]
    #alternative
    #df = df[~df['project_id'].str.contains('^[a-zA-Z]{2}.{14}$', na=False)]
    print (df)
              project_id  name
    3                N/A    Up
    4  DE-T-1999-08-8512  Down
    

    【讨论】:

    • 既然你正在做一个正则表达式匹配,你不妨也检查一下长度是否正确,所以你的掩码就变成了m = ~df['project_id'].str.match('[a-zA-Z]{2}.{14}$')
    • 如果您不打算使用.str.match,那么您需要锚定您的正则表达式,例如:^'[a-zA-Z]{2}.{14}$ 否则.str.contains 会认为:XXXXXXXUS-T-2018-08-110 是有效的。 ..
    • @JonClements - 我的正则表达式不是很好,为什么在这里使用'?谢谢。
    • 这是一个错字...应该是'^.... 其中^表示锚定到字符串的开头(.str.match的默认值)类似于@ 987654342@ 锚定到字符串的末尾...
    【解决方案3】:

    检查总长度是否为 16 或前两个字符不是字母:

    print(df[(df['project_id'].apply(lambda x: len(x) != 16)) | (df['project_id'].apply(lambda x: not x[0:2].isalpha()))])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多