【问题标题】:Skip operations on row if it is non numeric in pandas dataframe如果它在熊猫数据框中不是数字,则跳过对行的操作
【发布时间】:2018-01-17 16:40:41
【问题描述】:

我有一个数据框:

import pandas as pd
df = pd.DataFrame({'start' : [5, 10, '$%%', 20], 'stop' : [10, 20, 30, 40]})
df['length_of_region'] = pd.Series([0 for i in range(0, len(df['start']))])

我只想计算非零数值行值的区域长度,如果值不正确,则为带有错误注释的行计算跳过函数。这是我目前所拥有的:

df['Notes'] = pd.Series(["" for i in range(0, len(df['region_name']))])

for i in range(0, len(df['start'])):
    if pd.isnull(df['start'][i]) == True:
        df['Notes'][i] += 'Error: Missing value for chromosome start at region %s, required value;' % (df['region_name'][i])
        df['critical_error'][i] = True
        num_error = num_error+1
    else:
        try:
            #print (df['start'][i]).isnumeric()
            start = int(df['start'][i])
            #print start
            #print df['start'][i]
            if start == 0:
                raise ValueError
        except:
            df['Notes'][i] += 'Error: Chromosome start should be a non zero number at region %s; ' % (df['region_name'][i])
            #print df['start'][i]
            df['critical_error'][i] = True
            num_error = num_error+1
for i in range(0, len(df['start'][i])):
    if df['critical_error'][i] == True:
        continue
    df['length_of_region'][i] = (df['stop'][i] - df['start'][i]) + 1.0

但是,pandasdf['start'] 转换为 str 变量,即使我使用 int 进行转换,我也会收到以下错误:

df['length_of_region'][i] = (df['stop'][i] - df['start'][i]) + 1.0

TypeError: 不支持的操作数类型 -: 'numpy.int64' 和 'str'

我在这里缺少什么?感谢您的宝贵时间!

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    盯着代码看了很长一段时间后,找到了一个简单而优雅的修复方法,将df['start'][i]重新分配给start,我在try-except中使用如下:

    for i in range(0, len(df['start'])):
        if pd.isnull(df['start'][i]) == True:
            df['Notes'][i] += 'Error: Missing value for chromosome start at region %s, required value;' % (df['region_name'][i])
            df['critical_error'][i] = True
            num_error = num_error+1
        else:
            try:
                start = int(df['start'][i])
                df['start'][i] = start
                if start == 0:
                    raise ValueError
            except:
                df['Notes'][i] += 'Error: Chromosome start should be a non zero number at region %s; ' % (df['region_name'][i])
                #print df['start'][i]
                df['critical_error'][i] = True
                num_error = num_error+1
    for i in range(0, len(df['start'][i])):
        if df['critical_error'][i] == True:
            continue
        df['length_of_region'][i] = (df['stop'][i] - df['start'][i]) + 1.0
    

    重新分配起始变量,将其转换为 int 格式并帮助计算 length_of_region 仅适用于数字列

    【讨论】:

      【解决方案2】:

      您可以定义一个自定义函数来进行计算,然后将该函数应用于每一行。

      def calculate_region_length(x):
          start_val = x[0]
          stop_val = x[1]
          try:
              start_val = float(start_val)
              return (stop_val - start_val) + 1.0
          except ValueError:
              return None
      

      自定义函数接受一个列表作为输入。该函数将测试起始值以查看它是否可以转换为浮点数。如果不能,则将返回 None。这样,如果 '1' 存储为字符串,则该值仍然可以转换为浮点数并且不会被跳过,而示例中的 '$%%' 不能并且将返回 None

      接下来为每一行调用自定义函数:

      df['length_of_region'] = df[['start', 'stop']].apply(lambda x: calculate_region_legnth(x), axis=1)
      

      这将为start 不是不可转换字符串和None 其中start 是无法转换为数字的字符串的行创建带有(stop - start) + 1.0 的新列。

      然后,您可以根据返回 None 的行更新 Notes 字段,以识别缺少起始值的区域:

      df.loc[df['length_of_region'].isnull(), 'Notes'] = df['region_name']
      

      【讨论】:

      • 您好,感谢您的回答!我一直在寻找一种方法,在这种方法中,我不会大规模改变代码的架构并继续使用相同的格式,因为我正在以类似的方式计算相当多的其他变量。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 2015-05-18
      相关资源
      最近更新 更多