循环遍历R数据帧中的行?

时间:2018-07-23 14:25:47

标签: r loops for-loop dataframe

我正在R中处理多个大数据框架,并且试图编写可以修改每个框架的函数(给定一组通用参数)。一种功能给我带来麻烦(如下所示)。

RawData <- function(x)
{
  for(i in 1:nrow(x))
  {
    if(grep(".DERIVED", x[i,]) >= 1)
    {
      x <- x[-i,]
    }
  }
  for(i in 1:ncol(x))
  {
    if(is.numeric(x[,i]) != TRUE)
    {
      x <- x[,-i]
    }
  }
  return(x)
}

此函数的目的是双重的:首先,删除任何在其单元格中包含“ .DERIVED”字符串的行(使用grep);其次,删除所有非数字列(使用是数字)。在以下情况下出现错误:

if(grep(".DERIVED", x[i,]) >= 1)

该错误指出“参数长度为零”,我认为通常与向量中的NULL值相关联。但是,我在整个数据帧上使用了is.null,这给了我错误,并且它确认DF中没有空值。我确定我在这里缺少相对简单的东西。任何建议将不胜感激。

3 个答案:

答案 0 :(得分:1)

如果可以使用非base-R功能,则应该可以解决您的问题。 df是此处讨论的data.frame。它也比遍历行要快(如果可以避免,通常不建议这样做)。

library(dplyr)
library(stringr)

df %>%
  filter_all(!str_detect(., '\\.DERIVED')) %>%
  select_if(is.numeric)

您可以像其他任何操作一样使它成为函数:

mattsFunction <- function(dat){
  dat %>%
    filter_all(!str_detect(., '\\.DERIVED')) %>%
    select_if(is.numeric)
}

您可能应该给它起个更好的名字

答案 1 :(得分:0)

错误出在行上

if(grep(".DERIVED", x[i,]) >= 1)

当grep找不到术语“ .DERIVED”时,它将返回零长度的内容,您的不等式不会返回TRUE或FALSE,而是返回logical(0)。该错误告诉您if语句无法评估logical(0) >= 1

一个简单的例子:

if(grep(".DERIVED", "1234.DERIVEDabcdefg") >= 1) {print("it works")} # Works nicely, since the inequality can be evaluated
if(grep(".DERIVED", "1234abcdefg") > 1) {print("no dice")}

您可以将该行替换为if(length(grep(".DERIVED", x[i,])) != 0)

您还没有注意到其他事情,那就是您要删除循环中的行/列。假设您删除第5列,则下一个循环迭代(当i = 6时)将处理第7行! (这将导致错误Error in [。data.frame (x, , i) : undefined columns selected的结束)

答案 2 :(得分:0)

我更喜欢使用dplyr,但是如果您需要使用基本R函数,则可以使用一些没有if语句的方法来实现。

请注意,您应该考虑使用"\\.DERIVED"而不是".DERIVED"的正则表达式版本,这意味着“任何字符后跟DERIVED”。

我没有示例数据或输出,所以这是我最好的选择...

# Made up data
test <- data.frame(a = c("data","data.DERIVED","data","data","data.DERIVED"),
                   b = (c(1,2,3,4,5)),
                   c = c("A","B","C","D","E"),
                   d = c(2,5,6,8,9),
                   stringsAsFactors = FALSE)

# Note: The following code assumes that the column class is numeric because the
# example code provided assumed that the column class was numeric. This will not 
# detects if the column is full of a string of character values of only numbers.

# Using the base subset command
test2 <- subset(test,
                subset = !grepl("\\.DERIVED",test$a),
                select = sapply(test,is.numeric))

# > test2
#   b d
# 1 1 2
# 3 3 6
# 4 4 8


# Trying to use []. Note: If only 1 column is numeric this will return a vector
# instead of a data.frame
test2 <- test[!grepl("\\.DERIVED",test$a),]
test2 <- test2[,sapply(test,is.numeric)]

# > test2
#   b d
# 1 1 2
# 3 3 6
# 4 4 8