【问题标题】:How to identify string and alph-numeric string in python?如何在python中识别字符串和字母数字字符串?
【发布时间】:2020-03-30 19:47:17
【问题描述】:
Df1:
  Name    Emp_Id   Desgn  Salary
0 Rick    F912-1   Engg    4500
1 Monty   56Df1    Doc     6700
2 Chris   J45-12   Arch2   7800.0
3 Julie   Klgi     Engg-A  KL00
4 Mashy1  5670     Law_y   4100.0

Df2:

COL_NAME   DATATYPE
Name       string
EMP_Id     AlphaNum
Design     string
Salary     Floatorint 

如何遍历数据框以检查值数据类型是否有效? 我想根据 df2 数据类型信息检查每个列值数据类型并返回错误的数据类型值。例如,字符串列应包含字符串(无数字),字母数字数据类型必须是至少 1 个数字和 1 个字母的组合。

输出:

Col_name  value    dtype   Row_Num
Name       Mashy1  string     4
Emp_Id     Klgi    AlphaNum   3
Emp_Id     5670    AlphaNum   4
Design     Arch2   string     2
Salary     KL00    Floatorint 3

【问题讨论】:

  • 为什么 klgi 是字母数字的?
  • 为什么是KL00 Floatorint?
  • 为什么是“Mashy1”和“Arch2”字符串而不是字母数字?
  • klgi 不是字母数字,dtype 列是预期的数据类型,说明它应该是什么。
  • 输出中的 dtype 列就像预期的 dtype,我们在来自 Df2 的单元格中所期望的。

标签: python regex pandas


【解决方案1】:

虽然这可以使用正则表达式解决,但我选择了 Python 解决方案,借鉴了 here

首先,一个辅助函数来判断一个字符串是否包含一个数字。

def hasNumbers(inputString):
    return any(char.isdigit() for char in inputString)

其次,将对象分类为指定类型的函数。

def determine_type(x):
    # check if x is a number
    if isinstance(x, (int, float, np.int64, np.float64)):
        return "int or float"

    # check if x is a string
    elif isinstance(x, str):
        # check if the string contains a digit
        if hasNumbers(x):
            return "alphanumeric"
        else:
            # it's a string
            return "string"

请注意这里 intfloat 被转换为字符串的边缘情况。 “5”是字母数字。

让我们制作我们的数据框,并将任何可以转换为数字的内容转换为数字:

"""
  name    emp_id   design  salary
0 Rick    F912-1   Engg    4500
1 Monty   56Df1    Doc     6700
2 Chris   J45-12   Arch2   7800.0
3 Julie   Klgi     Engg-A  KL00
4 Mashy1  5670     Law_y   4100.0
"""
df1 = pd.read_clipboard().reset_index(drop=True)
df1 = df1.applymap(lambda x: pd.to_numeric(x, errors="ignore"))

display(df1)

输出:

     name  emp_id  design salary
0    Rick  F912-1    Engg   4500
1   Monty   56Df1     Doc   6700
2   Chris  J45-12   Arch2   7800
3   Julie    Klgi  Engg-A   KL00
4  Mashy1    5670   Law_y   4100

现在,让我们将此数据框melt 转换为您请求的格式,并应用我们的自定义函数。

# melt the df
df1_melted = df1.reset_index().melt(id_vars="index").sort_values("index")

# apply our function
df1_melted["type"] = df1_melted["value"].apply(determine_type)
print(df1_melted.head(10))

输出:

    index variable   value          type
0       0     name    Rick        string
5       0   emp_id  F912-1  alphanumeric
10      0   design    Engg        string
15      0   salary    4500  int or float
1       1     name   Monty        string
6       1   emp_id   56Df1  alphanumeric
11      1   design     Doc        string
16      1   salary    6700  int or float
2       2     name   Chris        string
17      2   salary    7800  int or float

这里的大部分工作是编写(破解)自定义函数来确定数据类型。我真的建议坚持使用内置类型,纯 Python 或 numpy。如果是字符串,那么你可以做进一步的分析。

【讨论】:

    【解决方案2】:

    这是一个使用正则表达式的解决方案。 首先,创建正则表达式模式并将预编译的正则表达式对象的“匹配”方法放入 df2:

    import re
    
    rnum= r"^(?=^\d*.?\d*$)[\d\.]+$"
    ralpha= r"(?i)^(?=.*[-_a-z])(?=.*\d)[-_a-z\d]+$"
    rstr= r"(?i)^[-_a-z]+$"
    
    df2["rx"]=df2.DATATYPE.replace({"string":re.compile(rstr).match, \
                                    "AlphaNum":re.compile(ralpha).match, \
                                    "Floatorint":re.compile(rnum).match})
    

    然后从它们创建一个 dict 并将其用于转换 df1:

    d= dict(df2[["COL_NAME","rx"]].values)
    r= df1[df1.transform(d).isna()]
    
        Name Emp_Id Design Salary
    0     NaN    NaN    NaN    NaN
    1     NaN    NaN    NaN    NaN
    2     NaN    NaN  Arch2    NaN
    3     NaN   Klgi    NaN   KL00
    4  Mashy1   5670    NaN    NaN
    

    格式化,并添加“data_type”列:

    r= r.stack().rename_axis(index=["row_num","col_name"]).reset_index(name="value")
    r["data_type"]= df2.set_index("COL_NAME").loc[r.col_name,"DATATYPE"].values   
    r= r.reindex(columns=["col_name","value","data_type","row_num"])
    
      col_name   value   data_type  row_num
    0   Design   Arch2      string        2
    1   Emp_Id    Klgi    AlphaNum        3
    2   Salary    KL00  Floatorint        3
    3     Name  Mashy1      string        4
    4   Emp_Id    5670    AlphaNum        4 
    

    注意:您也可以在 df2.rx 中使用非正则表达式函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2018-03-14
      相关资源
      最近更新 更多