【问题标题】:Identifying only numeric values from a column in a Data Frame- Python仅从数据框中的列中识别数值 - Python
【发布时间】:2021-02-09 09:02:25
【问题描述】:

我想要一个单独的列,如果列“ID”包含所有数值,则返回“是”,如果包含字母或字母数字值,则返回“否”。

ID      Result
3965      Yes
wyq8      No
RO_123    No
CMD_      No
2976      Yes

【问题讨论】:

    标签: python pandas numpy dataframe automation


    【解决方案1】:

    您可以在此处使用pd.Series.str.isnumeric

    df['Result'] = np.where(df['ID'].str.isnumeric(), 'YES', 'NO')
    
           ID Result
    0    3965    YES
    1    wyq8     NO
    2  RO_123     NO
    3    CMD_     NO
    4    2976    YES
    

    使用isnumeric 有一个警告,它不能识别float 数字。

    test = pd.Series(["9.0", "9"])
    test.str.isnumeric()
    
    0    False
    1     True
    dtype: bool
    

    如果您严格将YES 标记为int,则使用isnumeric,否则您可以在此处使用pd.Series.str.fullmatch(从1.1.0 版开始提供)。

    df['Result'] = np.where(df['ID'].str.fullmatch(r"\d+|\d+\.\d+", 'YES', 'NO')
    

    对于 re.fullmatch

    numeric_pat = re.compile(r"\d+|\d+\.\d+")
    def numeric(val):
        match = numeric_pat.fullmatch(val)
        if match: return 'YES'
        else: return 'NO'
    
    df['Result'] = df['ID'].apply(numeric)
    

    或者我们可以使用pd.to_numeric 和使用pd.Series.isna 的布尔掩码

    m = pd.to_numeric(df['ID'], errors='coerce').isna()
    df['Result'] = np.where(m, 'NO', 'YES')
    

    errors 参数设置为'coerce' 无法转换为数字值的值将设置为Nan

    test = pd.Series(['3965', 'wyq8', 'RO_123', 'CMD_', '2976'])
    pd.to_numeric(test)
    
    0    3965.0
    1       NaN
    2       NaN
    3       NaN
    4    2976.0
    Name: ID, dtype: float64
    

    或者你可以构建一个自定义函数

    def numeric(val):
        try:
            float(val)     # Using just `float` would suffice as int can be 
            return 'YES'   # converted to `float` so both `int`
                           # and `float` wouldnot raise any error
        except ValueError:
            return 'NO'
    
    df['Result'] = df['ID'].apply(numeric)
    

    注意float 也处理科学记数法,float("1e6") -> 1000000.0

    test = pd.Series(['1e6', '1', 'a 10', '1E6'])
    test.apply(numeric)
    
    0    YES
    1    YES
    2     NO
    3    YES
    dtype: object
    

    【讨论】:

      【解决方案2】:

      检查ID 是否包含non-digits,并使用~ 反转布尔选择。使用np.where,分配选项

      df['Result']=np.where(~df.ID.str.contains('(\D+)'),'Yes','N0')
      
           ID Result
      0    3965    Yes
      1    wyq8     N0
      2  RO_123     N0
      3    CMD_     N0
      4    2976    Yes
      

      正如@Cameron Riddell 所说。您也可以跳过反转布尔值并执行以下操作;

      df['Result']=np.where(df.ID.str.contains('(\D+)'),'No','Yes')
      

      【讨论】:

      • 与其反转布尔数组,为什么不将"No" 设为True 值,将"Yes" 设为False 值? np.where(df.ID.str.contains('(\D+)'),'No','Yes')
      • @Cameron Riddell 我们实际上可以。我的理念是让 OP 的答案尽可能可追溯,如果他们选择运行分解它。不过好点。
      • 当有字符串 '123 SO' 时,这会失败,使用 re.fullmatch 会反例。
      【解决方案3】:

      你可以使用.isnumeric()方法:

      df3["Result"] = df3["ID"].str.isnumeric().apply(lambda x: "No" if x == False else "Yes")
      

      [更新]:此方法仅适用于整数,其他情况请查看@Ch3steR 答案。

      【讨论】:

        猜你喜欢
        • 2021-12-10
        • 2021-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-18
        相关资源
        最近更新 更多