2015-02-05 69 views
0

我使用下面的代码将数据集拆分为两部分,并在每部分中执行类似的操作。这两个结果然后合并在一起。我知道我可能会描述拆分应用组合框架,但我无法想象如何简化下面的代码。拆分数据集,对每个组应用不同的操作,然后组合

数据集有4个要更新的变量。 4个变量中的每一个都有一个计算新值的公式,每个公式都有一个不同的公式,总共8个公式。

下面的代码可能会通过某种程度的矢量化得到改善吗?它似乎比必要的更冗长。我不确定如何为每个分割半部执行不同的操作(即使用不同的公式),除了下面的方法。

data <- structure(list(site = c(1L, 1L, 1L, 1L, 1L, 1L), plot = 1:6, 
    C = c(40L, 30L, 10L, 5L, 0L, 0L), E = c(0L, 0L, 0L, 10L, 
    20L, 45L), M = c(0L, 0L, 0L, 0L, 0L, 10L), P = c(1000L, 900L, 
    800L, 500L, 200L, 50L), FF = c(1L, 1L, 1L, 0L, 0L, 0L)), .Names = c("site", 
"plot", "C", "E", "M", "P", "FF"), class = "data.frame", row.names = c(NA, 
-6L)) 

df1 <- data[data$FF == 1,] 
df0 <- data[data$FF == 0,] 

df1$C <- df1$C * 1.1 
df1$E <- df1$E * 0.9 
df1$M <- df1$M * 0.1 
df1$P <- df1$P * 1.01 

df0$C <- df0$C * 0.8 
df0$E <- df0$E * 1.05 
df0$M <- df0$M * 1.01 
df0$P <- df0$P * 1.01 

df.new <- rbind(df1, df0) 
+3

等一下,你用plyr和data.table标记了这个,但还没有探讨如何使用它们呢? – Frank 2015-02-05 20:23:26

+0

我确实通过其他SO问题和答案探索plyr和data.table,以及一些我在这里没有重现的微弱尝试。但是,我认为如果我有足够的资金与他们一起编写代码,这两种方法似乎都是合适的。我可以发布非功能性代码片段。谢谢。 – nofunsally 2015-02-05 21:21:34

回答

5

有许多工具在R.拆分申请,结合我会倾向于使用data.table包:

require(data.table) 
mydt <- data.table(data) 
mycols <- c('C','E','M','P') 
newcols <- paste0(mycols,'new') 
my1vec <- c(1.1,.9,1,1.01) 
my0vec <- c(.8,1.05,1.01,1.01) 

mydt[FF==1,(newcols):=mapply(`*`,my1vec,.SD,SIMPLIFY=FALSE),.SDcols=mycols] 
mydt[FF==0,(newcols):=mapply(`*`,my0vec,.SD,SIMPLIFY=FALSE),.SDcols=mycols] 

我把新值在新列。如果您想覆盖旧值(如原始代码所做的那样),请使用(mycols)代替(newcols)

0

有可能是一个更简单的方法来做到这一点,但我觉得这4条线路做你想要什么:

df.new = data 
df.new$C = ifelse(data$FF==1,data$C*1.1,data$C*0.8) 
df.new$E = ifelse(data$FF==1,data$E*0.9,data$E*1.05) 
df.new$M = ifelse(data$FF==1,data$M*0.1,data$M*1.01) 
df.new$P = ifelse(data$FF==1,data$P*1.01,data$P*1.01) 
0

试试这个:

#define the coefficients in the FF==1 case 
FF1coeffs<-c(1.1,0.9,0.1,1.01) 
#define the coefficients in the FF==0 case 
FF0coeffs<-c(0.8,1.05,1.01,1.01) 
#multiply 
data[,3:6]*(rep(FF1coeffs,each=nrow(data))*data$FF+(1-data$FF)*rep(FF0coeffs,each=nrow(data))) 
1

结合bydo.call这样:

do.call(rbind, 
    by(data,data$FF, 
    function(data)data*matrix(c(1,1,.8,1.05,1.01,1.01,1), 
     ncol=ncol(data),nrow=nrow(data),byrow=TRUE))) 

也就是说,使用by沿着data$FF分割您的data。将每个块按照适当的矩阵进行相乘(这是匿名的function)。最后,do.callrbind函数将结果一起绑定到一起。

如果需要,按FF列对结果进行排序。

1

您也可以使用within并使用FF作为数字变量。它不像一些答案那么简短,但它有点冗长。

df.new <- within(data, { 
    C = C * (0.8 + 0.3 * FF) 
    E = E * (1.05 - 0.15 * FF) 
    M = M * (1.01 - 0.91 * FF) 
    P = P * 1.01 }) 
相关问题