动态构造转换语句

时间:2012-10-21 17:52:13

标签: r

我有一个包含多个(数字)列的数据框,并希望创建一个新的数据框,其列是原始列。

> df <- data.frame(cbind(id=LETTERS[1:10],  
wheat=c(123,234,345,456,678,987,876,654,432,321),barley=c(135,975,246,864,357,753,468,642,579,531)))
> df
   id wheat barley
1   A   123    135
2   B   234    975
3   C   345    246
4   D   456    864
5   E   678    357
6   F   987    753
7   G   876    468
8   H   654    642
9   I   432    579
10  J   321    531
> rankeddf <- transform(df, wheat=rank(wheat), barley=rank(barley))
> rankeddf
   id wheat barley
1   A     1      1
2   B     2     10
3   C     4      2
4   D     6      9
5   E     8      3
6   F    10      8
7   G     9      4
8   H     7      7
9   I     5      6
10  J     3      5

问题是,列的数量和名称各不相同。我有一个指定它们的向量:

cols <- c("wheat", "barley")

如何动态构建transform语句?或者甚至遍历cols向量,在每次迭代时应用一次transform语句?我猜这个答案将与evalevalq有关,但我还没有完全了解它们。例如,

> rankeddf2 <- df
> for (col in cols) {rankeddf2 <- transform(rankeddf2, evalq(paste(col,"=rank(",col,")",sep="")))}
> rankeddf2
   id wheat barley
1   A   123    135
2   B   234    975
3   C   345    246
4   D   456    864
5   E   678    357
6   F   987    753
7   G   876    468
8   H   654    642
9   I   432    579
10  J   321    531

没有做到这一点。

或者,还有另一种方法吗?

2 个答案:

答案 0 :(得分:6)

您可以使用lapplyrank()

来执行此操作
as.data.frame(lapply(df[, cols], rank))
   wheat barley
1      1      1
2      2     10
3      4      2
4      6      9
5      8      3
6     10      8
7      9      4
8      7      7
9      5      6
10     3      5

好的,所以在这个过程中你会失去第一列,但这很容易添加回来:

data.frame(id=df[[1]], lapply(df[, cols], rank))
   id wheat barley
1   A     1      1
2   B     2     10
3   C     4      2
4   D     6      9
5   E     8      3
6   F    10      8
7   G     9      4
8   H     7      7
9   I     5      6
10  J     3      5

答案 1 :(得分:4)

我喜欢将transform()和相关的with()within()视为语法糖,这些语法在顶层交互式有用,但经常通过{{1}进行子集和替换},'['()等更容易用于这样的工作:

'[<-'()

> df2 <- df ## copy > df2[, cols] <- apply(df[, cols], 2, rank) > df2 id wheat barley 1 A 1 1 2 B 2 10 3 C 4 2 4 D 6 9 5 E 8 3 6 F 10 8 7 G 9 4 8 H 7 7 9 I 5 6 10 J 3 5 '['()已经按照您的要求执行了操作,因此您尝试使用子集和替换功能强制'[<-'()执行已经实现的操作。