2011-02-16 44 views
5

一次操作多列(或多行)的编程方式是什么?考虑下面的例子:同时在多列上操作

df2 <- data.frame(a = 1:10, b = 5:14, c = 10:1, d = 14:5) 

我想创建两个包含a/b和c/d比率的新列。为了简单起见,我们假设所有列之间的空间关系是一致的。由于只有两列作,一个还不如做这样的事情:

df2$ab <- with(df2, a/b) 
df2$cd <- with(df2, c/d) 

df2 <- transform(df2, ab = a/b, cd = c/d) 

要创建这样一个最终产品:

a b c d  ab  cd 
1 1 5 10 14 0.2000000 0.7142857 
2 2 6 9 13 0.3333333 0.6923077 
3 3 7 8 12 0.4285714 0.6666667 
4 4 8 7 11 0.5000000 0.6363636 
5 5 9 6 10 0.5555556 0.6000000 
6 6 10 5 9 0.6000000 0.5555556 
7 7 11 4 8 0.6363636 0.5000000 
8 8 12 3 7 0.6666667 0.4285714 
9 9 13 2 6 0.6923077 0.3333333 
10 10 14 1 5 0.7142857 0.2000000 

但如果有你需要迭代100列的列?我通常使用Excel或SQL来连接代码并将其放在我的.R脚本中,但似乎必须有一种方法来解决这个问题。

完全公开:这个问题是关于一个问题cross validated我在那里砍了一个不能最优化的解决方案。

回答

4

尝试这种解决方案:

df2 <- data.frame(a = 1:10, b = 5:14, c = 10:1, d = 14:5, e = 34:43, f = 56:65) 

n <- ncol(df2) 
s1 <- seq(1, n, 2) 
s2 <- seq(2, n, 2) 

df2[paste(names(df2)[s1], names(df2)[s2], sep="")] <- df2[, s1]/df2[, s2] 
+0

您的编辑解决方案快几乎相当于for循环我来了与...一起。我会在稍后更新性能测试。谢谢!将结果对象绑定到自身将证明比新解决方案慢。 – Chase 2011-02-16 22:29:29

0

这个怎么解决呢?它避免了cbind多次荷兰国际集团的对象本身:

for (i in seq(1, ncol(df2), by = 2)) { 
    df2[, paste(names(df2)[i], names(df2)[i+1], sep = "", collapse = "")] <- df2[, i]/df2[, i + 1] 
} 

编辑:它看起来像我的解决办法是略高于@ djhurio的

> set.seed(42) 
> df2 <- data.frame(
+  a = sample(1:10, 10e6, T) 
+ , b = sample(1:10, 10e6, T) 
+ , c = sample(1:10, 10e6, T) 
+ , d = sample(1:10, 10e6, T) 
+) 
> 
> system.time(
+ for (i in seq(1, ncol(df2), by = 2)) { 
+ df2[, paste(names(df2)[i], names(df2)[i+1], sep = "", collapse = "")] <- df2[, i]/df2[, i + 1] 
+ } 
+) 
    user system elapsed 
    1.06 0.64 1.70 
> 
> foo <- function(df2) { 
+ n <- ncol(df2) 
+ s1 <- seq(1, n, 2) 
+ s2 <- seq(2, n, 2) 
+ df2 <- cbind(df2, df2[, s1]/df2[, s2]) 
+ names(df2)[(n+1):ncol(df2)] <- paste(names(df2)[s1], names(df2)[s2], sep="") 
+ return(df2) 
+ } 
> 
> set.seed(42) 
> df2 <- data.frame(
+  a = sample(1:10, 10e6, T) 
+ , b = sample(1:10, 10e6, T) 
+ , c = sample(1:10, 10e6, T) 
+ , d = sample(1:10, 10e6, T) 
+) 
> system.time(foo(df2)) 
    user system elapsed 
    1.73 0.85 2.57