【问题标题】:Use np.where extract item occurring error index out of range使用 np.where 提取项目出现错误索引超出范围
【发布时间】:2020-01-01 09:31:06
【问题描述】:

我想从两列中提取一个项目,使用 np.where,DataFrame 如下: (总共 100,000+ 行)

添加说明:“eNBID”并不总是“ID”的第三部分,数据非常脏。

       ID         eNBID
460-00-2354-9     2354
4600023549        2354
46001368511       6789
4600332783112     32783

我想要的结果是:

       ID         eNBID     CI
460-00-2354-9     2354       9
4600023549        2354       9
46001368511       6789       11
4600332783112     32783      112

我的代码是:

df['Ci'] = np.where(df['ID'].astype(str).str.contains(r'-',na=False,regex=True), \
           df['ID'].apply(lambda x:re.split('-',str(x))[-1], \
           df.apply(lambda x:re.findall('([\w]{5})'+'([\w]{%d}'%(len(str(x.eNBID)))+'(\w*)',str(x.ID))[0][-1], axis=1))

错误是:

IndexError:('list index out of range','occurred at index 0')

这是我的新代码:

cond = df['ID'].astype(str).str.contains('-',na=False,regex=True)
df['CI'] = np.where(cond,df['ID'].apply(lambda x:re.split('-',str(x))[-1]), \
          df[~cond].apply(lambda x:re.findall('([\w]{5})'+'([\w]{%d}'%(len(str(x.eNBID)))+'(\w*)',str(x.ID))[0][-1], axis=1)) if len(str(x.eNBID))<(len(str(x.ID))-5) else "null", axis=1))

错误是:

ValueError:operands could not be broadcast together with shapes(100883,)(100883,)(78,)

谁能帮帮我?

【问题讨论】:

  • @Erfan 我假设 CI 是在 eNBID 之后的 ID 中找到的数字(至少这与提供的示例一致)
  • 对不起,是我的错,我没说清楚,“eNBID”并不总是“ID”的第三部分,数据很脏,只有“eNBID”的长度"可以使用。

标签: pandas numpy data-cleaning


【解决方案1】:

试试这个

df['s']=df['ID'].replace('-','', regex=True)
df['Ci'] = df.apply(lambda x: x['s'][(5+len(str(x.eNBID))):], axis=1)
df.drop('s', axis=1, inplace = True)

输出

     ID            eNBID    Ci
0   460-00-2354-9   2354    9
1   4600023549      2354    9
2   46001368511     6789    11
3   4600332783112   32783   112

【讨论】:

  • 非常感谢,因为数据非常脏,“eNBID”并不总是“ID”的第三部分,所以你的代码只能在某些条件下工作
  • 你能更新你的数据来代表所有场景吗?我们只能使用您提供的数据。在我的解决方案中,“eNBID”在哪里并不重要。我正在使用 eNBID 来拆分 ID,然后取它之后的部分。
  • 对不起,是我的错,我能看懂你的代码,我刚刚更新了我的数据演示。
  • 第三行的逻辑是什么?我想不通。 6789 根本不是 ID 的一部分。
  • 脏数据没有逻辑,只能使用“eNBID”的长度。
【解决方案2】:

因为这是在R 中标记的,所以这里有一个解决方案:

data$CI = sapply(1:nrow(data),function(x){
  gsub(paste0(".*",data$eNBID[x],"-?"),"",data$ID[x])
})

             ID eNBID  CI
1 460-00-2354-9  2354   9
2    4600023549  2354   9
3   46001368511 36851   1
4 4600332783112 32783 112

我们删除直到eNBID 之前的所有字符,以及(可选)- 字符。

数据

data = read.table(textConnection(" 
460-00-2354-9     2354
                                 4600023549        2354
                                 46001368511       36851
                                 4600332783112     32783"),stringsAsFactors=FALSE)
names(data)=c("ID","eNBID")

【讨论】:

    【解决方案3】:

    您使用renp.where 的逻辑几乎就在那里:

    import re
    
    df['CI'] = np.where(df['ID'].str.contains('-'),
                        df.apply(lambda x: re.findall(f'(?<={x.eNBID}\-)(\d+)', x['ID']), axis=1),
                        df.apply(lambda x: re.findall(f'(?<={x.eNBID})(\d+)', x['ID']), axis=1))
    
    df['CI'] = df['CI'].str.join('')
    

    输出

                  ID  eNBID   CI
    0  460-00-2354-9   2354    9
    1     4600023549   2354    9
    2    46001368511  36851    1
    3  4600332783112  32783  112
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多