4

我有一个包含大量变量的数据框。我通过将一些旧变量加在一起来创建新变量。我用来这样做的代码是:

name_of_data_frame<- transform(name_of_data_frame, new_variable=var1+var2 +....)

当变换在其中一个观察中遇到 NA 时,它会在新变量中返回“NA”,即使它添加的其他一些变量不是 NA。

例如 if var1= 4, var2=3, var3=NA, then using transform, if I did var1+var2+var3it would give out NA,而我希望它给我 7。

我不想NA在数据框中将我的 s 重新编码为零,因为我可能需要稍后再参考NAs,所以不想将NAs 与真正的观察结果混淆0

NA关于如何以上述方式使用转换函数绕过 R 处理 s 的任何帮助都会很棒(或者如果有替代函数可以使用,那也很棒)。

请注意,我并不总是对彼此相邻的变量求和,我还经常对变量进行除法、乘法、减法等。

4

2 回答 2

10

我的第一个直觉是建议使用sum(),因为那时你可以使用na.rm参数。但是,这不起作用,因为sum()将它的参数减少为单个标量值,而不是向量。

这意味着您需要编写一个parallel sum函数。我们称它为psum(),类似于基本 R 函数pmin()pmax()

psum <- function(..., na.rm=FALSE) { 
  x <- list(...)
  rowSums(matrix(unlist(x), ncol=length(x)), na.rm=na.rm)
} 

现在设置一些数据并用于psum()获取所需的向量:

dat <- data.frame(
  x = c(1,2,3, NA),
  y = c(NA, 4, 5, NA))

transform(dat, new=psum(x, y, na.rm=TRUE))
   x  y new
1  1 NA   1
2  2  4   6
3  3  5   8
4 NA NA   0

同样,您可以定义 a parallel product,或者pprod()像这样:

pprod <- function(..., na.rm=FALSE) { 
  x <- list(...)
  m <- matrix(unlist(x), ncol=length(x))
  apply(m, 1, prod, na.rm=TRUE)
} 

transform(dat, new=pprod(x, y, na.rm=TRUE))
   x  y new
1  1 NA   1
2  2  4   8
3  3  5  15
4 NA NA   1

此示例pprod为您想要做的事情提供了一个通用模板:创建一个函数,用于apply()将输入矩阵汇总到所需的向量中。

于 2012-08-27T10:33:37.303 回答
2

使用rowSumsprod可以帮助您。

set.seed(007) # Generating some data
DF <- data.frame(V1=sample(c(50,NA,36,24,80, NA), 15, replace=TRUE),
                 V2=sample(c(70,40,NA,25,100, NA), 15, replace=TRUE),
                 V3=sample(c(20,26,34,15,78,40), 15, replace=TRUE))

transform(DF, Sum=rowSums(DF, na.rm=TRUE)) # Sum (a vector of values)
transform(DF, Prod=apply(DF, 1, FUN=prod, na.rm=TRUE)) # Prod (a vector of values)

# Defining a function for substracting (resta, in spanish :D)
resta <- function(x) Reduce(function(a,b) a-b,  x <- x[!is.na(x)])
transform(DF, Substracting=apply(DF, 1, resta))

# Defining a function for dividing 
div <- function(x) Reduce(function(a,b) a/b,  x <- x[!is.na(x)])
transform(DF, Divsion=apply(DF, 1, div))
于 2012-08-27T11:10:18.090 回答