r if语句遇到错误:参数长度为零

时间:2017-05-05 05:14:15

标签: r if-statement

以下是数据:

1:
30878
2647871
1283744
2488120
317050
1904905
1989766
14756
1027056
1149588
1394012
1406595
2529547
1682104
2625019
2603381
1774623
470861
712610
1772839
1059319
2380848
548064
10:
1952305
1531863
1000:
2326571
977808
1010534
1861759
79755
98259
1960212
97460
2623506
2409123
...

后跟':'的数字表示它是一个movieID,然后以下几行是customerID,我想写一个循环来检查数据是否包含':',这是我试过的代码:

for (i in 1:length(line)){
  #print(line[i])
  if(grep(':', line[i])==1 ){
    movieID<-as.integer(substr(line[i],1,nchar(line[i])-1)  )
    next
  } 
  else{
    customerID<-as.integer(line[i])
    #do something
  }
}

当我运行此代码时,发生错误,错误是:参数的长度为零 我搜索了这个错误,然后我改变了if语句:

if( !is.na(line[i]) && nchar(line[i])>1 && grep(':', line[i])==1 )

仍然存在错误:缺少需要TRUE / FALSE的值

我无法解决它。 这是代码I:

for (i in 1:27){
  #print(testData[i])
  if(grep(':', testData[i])==1 ){
    movieID<-as.integer(substr(testData[i],1,nchar(testData[i])-1)  )
    print(testData[i])
    next
  }else{
    customerID<-as.integer(testData[i])
    print(movieID)
    print(customerID)
 #print(subset.data.frame(mydata[[movieID]],mydata[[movieID]]$customerID==customerID) )
  }
}

这是输出和错误:

[1] "1:"
Error in if (grep(":", testData[i]) == 1) { : argument is of length zero

看起来错误发生在else语句中。

2 个答案:

答案 0 :(得分:1)

错误是因为如果您要查找的字符串不存在,grep将返回logical(0)。因此,您的循环在i=2上失败,正如您在循环中断时查看i的值时所看到的那样。

如果您使用grepl代替,您的循环按计划运行(建立在@Akarsh Jain的答案上):

movieID<-array() 
customerID<-array()

for (i in 1:length(testData)){

  if(grepl(':', testData[i])){
    movieID[i]<-as.integer(substr(testData[i],1,nchar(testData[i])-1)  )
    next
  } else{
    customerID[i]<-as.integer(testData[i])

  }
}
当然,问题是这是多么有用。我假设你想以某种方式在movieID上分割你的数据,你可以使用dplyrtidyr轻松地做到这一点:

library(dplyr)
library(tidyr)
#put your testData in a dataframe
testDf <- data.frame(customerID = testData)

newDf <- testDf %>% 
#identify rows with :
         mutate(movieID = ifelse(grepl(":",customerID), customerID, NA)) %>%
#fill all NA values in movieID with the previous non-NA value:         
         fill(movieID) %>%
#remove lines where customerID has a ":":
         filter(!grepl(":",customerID))

输出:

    customerID movieID
1    30878       1
2  2647871       1
3  1283744       1

虚假数据

testData <- read.table(text='1:
30878
                                 2647871
                                 1283744
                                 2488120
                                 317050
                                 1904905
                                 1989766
                                 14756
                                 1027056
                                 1149588
                                 1394012
                                 1406595
                                 2529547
                                 1682104
                                 2625019
                                 2603381
                                 1774623
                                 470861
                                 712610
                                 1772839
                                 1059319
                                 2380848
                                 548064
                                 10:
                                 1952305
                                 1531863
                                 1000:
                                 2326571
                                 977808
                                 1010534
                                 1861759
                                 79755
                                 98259
                                 1960212
                                 97460
                                 2623506
                                 2409123', stringsAsFactors=FALSE)[[1]]

答案 1 :(得分:0)

  

虽然线路名称没有效果,但从未使用&#34; line&#34;作为一个名字   object,因为它是R的stats包中的函数名称。

问题是您每次都要为对象分配一个新值&#34; movieID &#34;或&#34; customerID &#34;而不是他们的索引作为循环进度。

每次&#34; movieID&#34;和&#34; customerID&#34;被新值取代。

要为数组索引赋值,您必须首先在外部循环中创建一个空数组。

请更换&#34; line&#34;任何其他对象名称。

movieID<-array() 
customerID<-array()

    for (i in 1:length(line)){
      #print(line[i])
      if(grep(':', line[i])==1 ){
        movieID[i]<-as.integer(substr(line[i],1,nchar(line[i])-1)  )
        next
      } 
      else{
        customerID[i]<-as.integer(line[i])
        #do something
      }
    }

希望这可能有助于@cloudiyang:)