聚合数据时出错

时间:2016-05-09 00:30:01

标签: r

我正在开发一个大数据数据框。  第一列包含字符串值,并且从其上的第二列包含数字数据。然而,在描述的第二个块中,有一些NA无法删除整个行或列,因为甚至会删除重要数据 我想创建一个包含相同第一列的新矩阵,但我想要新的数值数据,计算为每行与包含所有数值之和的新行之间的比率;这就是我所做的:

df1<- df[,-(1)]
tot<- colSums(df1, na.rm = TRUE)
ratio <- df1 / rep(tot, each = nrow(df1))
firstcol <- df[1]
data <- cbind(firstcol ,ratio)

在此之后,我希望按第一列聚合所有值:

agg<- aggregate(. ~ firstColName, data, sum)

但这样做会给我一个错误:

Error in aggregate.data.frame(lhs, mf[-1L], FUN = FUN, ...) : no rows to   aggregate

我尝试进行相同的聚合,不包括这部分代码:

ratio <- data / rep(tot, each = nrow(df1))

结果如下:

df1<- df[,-(1)]    
firstcol <- df[1]
data <- cbind(firstcol ,df1)
agg<- aggregate(. ~ firstColName, data, sum)

在这种情况下它完美地工作,所以我认为原因只是使用比率公式。 我应该使用其他方式进行操作吗?

1 个答案:

答案 0 :(得分:3)

很难猜到发生了什么,却没有真正看到你运行你的R代码。由于您似乎没有显示出对变量名称的良好管理,因此您可能会在实验期间屏蔽变量。

我们浪费了大量时间来猜测发生了什么。我建议,我们尝试了一个健壮的代码版本。在下文中,我为您提供了一个函数,将您的数据框作为唯一参数。 函数内部的变量不会与外部变量冲突,即使它们具有相同的名称

foo <- function (df) {
  error.default <- getOption("error")
  options(error = utils::recover)
  n <- nrow(df)
  value_df <- df[, -1]  ## data frame with values
  tot <- colSums(value_df, na.rm = TRUE)  ## column sums
  if (any(is.na(tot))) stop("NA detected in column sums! Exit!")
  ratio <- value_df / rep(tot, each = n)  ## rescaling
  string_df <- df[1]
  if (nrow(string_df) != nrow(ratio)) stop("dimension dismatch!!")
  cat("\n")
  data <- cbind(string_df ,ratio)
  cat("data summary:\n")
  cat(paste("number of rows: ", n, "\n",sep = ""))
  cat(paste("number of columns: ", ncol(data), "\n",sep = ""))
  ## NA summary: critical because aggregate will drop NA rows
  ## when all rows are dropped, aggregate complains "no row to aggregate"
  data <- na.omit(data)
  cat(paste("The number of non-NA rows passed to aggregate:", nrow(data))); cat("\n")
  cat("\n")
  if (nrow(data) == 0) stop("All rows are dropped! Exit!!")
  formula <- as.formula(paste(". ~", colnames(df)[1]))
  cat("the formula is: ")
  print(formula); cat("\n")
  agg <- aggregate(formula, data, FUN = sum)
  cat("aggregation success!!\n\n")
  options(error = error.default)
  return(agg)
  }

agg <- foo(df)

如果有任何错误消失,请将错误消息打印给我。

错误检测

根据上述功能的报告,当应用于您的完整数据时,我可以使用以下简单示例恢复您所处的场景。

以前,您提供的测试数据框是:

VAL1 <- c("AA", "BB", "CC", "DD", "BB", "DD", "AA", "DD")
Num1 <- c(1, 2, 1, 3, 4, 4, 6, 2) 
Num2 <- c(3, 3, 2, 1, 1, 2,4, 4) 
Num3 <- c(2, 2, 3, 4, 3, 5, 5, 7) 
df <- data.frame(VAL1, Num1, Num2, Num3)

当您进行聚合时,这将正常工作。现在让我们尝试这样的事情:

VAL1 <- c("AA", "BB", "CC", "DD", "BB", "DD", "AA", "DD")
Num1 <- c(NA, NA, 1, 3, 4, 4, 6, 2) 
Num2 <- c(3, 3, NA, NA, NA, 2,4, 4) 
Num3 <- c(2, 2, 3, 4, 3, NA, NA, NA) 
df <- data.frame(VAL1, Num1, Num2, Num3)

然后,你会得到什么?确切地说,您的完整数据集发生了什么。虽然每个列的所有条目都没有NA,但它们一起将所有行标记为NA Aggregate会删除包含至少一个NA 的所有行。这是aggregate的默认选项,有关参数?aggregate,请参阅na.action

你能做什么?

由于您不想删除所有NA,因此您需要将其替换为一些合理的数值。在我看来,将所有NA设置为0在您的问题中是合理的。当您使用tot<- colSums(df1, na.rm = TRUE)时,这相当于首先将所有NA设置为0,然后应用普通版本tot<- colSums(df1)

如果您同意,我们可以这样做:

df[is.na(df)] <- 0   ## set all NA to 0

foo <- function (df) {
  n <- nrow(df)
  value_df <- df[, -1]  ## data frame with values
  tot <- colSums(value_df)  ## column sums
  ratio <- value_df / rep(tot, each = n)  ## rescaling
  string_df <- df[1]
  data <- cbind(string_df ,ratio)
  formula <- as.formula(paste(". ~", colnames(df)[1]))
  aggregate(formula, data, FUN = sum)
  }

agg <- foo(df)   ## use `NA` corrected df to aggregate

这应该有用。