在R中对因子的级别进行排序和编号

3

如果我有以下数据框G:

z    type   x   
1     a     4
2     a     5 
3     a     6
4     b     1
5     b     0.9
6     c     4

我想获取:

z    type   x   y
3     a     6   3
2     a     5   2
1     a     4   1
4     b     1   2
5     b     0.9 1
6     c     4   1

我希望对数据框中的整个数据根据向量 x 来按type 分类进行排序。获取每个级别的长度a = 3 b = 2 c = 1,然后以递减的方式在新向量y中编号。

我目前的起点是使用 sort()

tapply(y, x, sort)

首先尝试使用sapply进行拆分是否最佳?

2个回答

7

有很多种方法可以实现这个目标。以下是一种使用基本的R语言和向量化编码的两步解决方案(没有使用任何apply函数):

  1. 使用orderxtfrm对数据进行排序。
  2. 使用rlesequence生成序列。

复制你的数据:

dat <- read.table(text="
z    type   x   
1     a     4
2     a     5 
3     a     6
4     b     1
5     b     0.9
6     c     4
", header=TRUE, stringsAsFactors=FALSE)

两行代码:

r <- dat[order(dat$type, -xtfrm(dat$x)), ]
r$y <- sequence(rle(r$type)$lengths)

结果为:

r
  z type   x y
3 3    a 6.0 1
2 2    a 5.0 2
1 1    a 4.0 3
4 4    b 1.0 1
5 5    b 0.9 2
6 6    c 4.0 1

order函数的调用稍微有些复杂。由于您要按升序排序一列,按降序排序另一列,因此需要使用辅助函数xtfrm。详见?xtfrm获取更多信息,但也可以在?order中找到相关描述。


嘿,两种解决方案都很棒。我之前没有见过xtfrm,非常有用。我想让x中的最高数字拥有最高的y,所以从xtfrm中删除了-,结果完美无缺,谢谢。 - user1322296
@Andrie 我之前也没见过 xtfrm,但不太明白它的作用。它在这里做了什么,负数不能做到吗?[帮助文件对这个函数的解释并不是很好] - Tyler Rinker
@user1322296 好的,那么你根本不需要使用 xtfrm - 它只会减慢速度。 - Andrie
@TylerRinker,“xtfrm”习惯用法也适用于字符串,但在这种情况下,您是正确的,不需要它。 - Andrie

4

我更喜欢Andrie的:

dat <- read.table(text="z    type   x   
1     a     4
2     a     5 
3     a     6
4     b     1
5     b     0.9
6     c     4", header=T)

三行代码:

dat <- dat[order(dat$type), ]
x <- by(dat, dat$type, nrow)
dat$y <- unlist(sapply(x, function(z) z:1))

我修改了我的回复以适应Andrie提到的评论。这样做是可行的,但如果你选择这种方法而不是Andrie的方法,那么你就是疯了。


你需要将最后一个 rep(x,x) 替换成 seq_len(x),然后它就能正常工作了。不错的解决方案。 - Andrie
@Andrie,我认为它目前能够正常工作。第二行给出了每个因子的长度(就是你使用rle的作用),即c(3, 2, 1)。然后我使用rep函数将每个长度重复该次数。试着运行一下,看看结果。 - Tyler Rinker
没事,我误解了海报想要表达的意思。现在我明白了。 - Tyler Rinker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接