1. 先来认识三个函数:sort(), order(), rank()
> sort(c(2,4,6,7,8,5))
[1] 2 4 5 6 7 8
> order(c(2,4,6,7,8,5))
[1] 1 2 6 3 4 5
> rank(c(2,4,6,7,8,5))
[1] 1 2 4 5 6 3
第一个很好理解,就是把一串数从小到大排列;
第二个不好理解,它也是从小到大在原向量中找数,但返回数对应的索引值
。即从小到大依次是:第1个数、第2个数、第6个数、第3个数...
rank()按照原向量的顺序,给出各个元素的排名。
给你一个数值向量,不清楚是否有重复值,现在需要返回升序的前4个数,怎么做?
> sort(c(2,4,6,7,8,5))[1:4]
[1] 2 4 5 6
> c(2,4,6,7,8,5)[order(c(2,4,6,7,8,5))[1:4]]
[1] 2 4 5 6
> sort(c(2,4,6,7,8,5)[rank(c(2,4,6,7,8,5))<=4])
[1] 2 4 5 6
2. 《ggplot2图形艺术》第一版的一个例子
求各个分组中carat最小的两个值
ddply(diamonds,.(color),subset,order(carat)<=2)
order(carat)<=2
这种做法是错的,我们并不是要求索引值为1,2
对应的数,而是order(carat)返回的向量的前两个索引值
对应的数。
这是返回值,待会儿可以回过头来看一下carat这一列。
> ddply(diamonds,.(color),subset,order(carat)<=2)
carat cut color clarity depth table price x y z
1 0.30 Ideal D SI1 62.1 56 552 4.30 4.33 2.68
2 0.24 Very Good D VVS1 61.5 60 553 3.97 4.00 2.45
3 0.23 Very Good E VS1 59.5 58 402 4.01 4.06 2.40
4 0.26 Very Good E VVS1 63.4 59 554 4.00 4.04 2.55
5 0.23 Very Good F VS1 60.9 57 357 3.96 3.99 2.42
6 0.23 Very Good F VS1 59.8 57 402 4.04 4.06 2.42
7 0.23 Very Good G VVS2 60.4 58 354 3.97 4.01 2.41
8 0.23 Ideal G VS1 61.9 54 404 3.93 3.95 2.44
9 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53
10 0.34 Ideal H VS2 60.4 57 555 4.54 4.57 2.75
11 0.30 Ideal I SI2 62.0 54 348 4.31 4.34 2.68
12 0.36 Ideal I VS2 61.9 56 556 4.54 4.57 2.82
13 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
14 1.01 Very Good J SI2 63.3 53 3088 6.35 6.31 4.01
也许我们可以用rank()函数试一下:
> ddply(diamonds,.(color),subset,rank(carat) <=2)
carat cut color clarity depth table price x y z
1 0.20 Ideal D VS2 61.5 57 367 3.81 3.77 2.33
2 0.20 Premium D VS2 62.3 60 367 3.73 3.68 2.31
3 0.20 Premium D VS2 61.7 60 367 3.77 3.72 2.31
4 0.20 Premium F VS2 62.6 59 367 3.73 3.71 2.33
5 0.23 Ideal I VVS1 63.0 56 414 3.94 3.90 2.47
6 0.23 Premium I VVS1 60.5 61 414 3.98 3.95 2.40
7 0.23 Ideal J VS1 62.8 56 340 3.93 3.90 2.46
为什么只有7行记录,并且color为D有三行,E,G,H都没有, F,J只有一行?
rank处理有重复的数值序列时,排名可能出现小数(重复值两个)或缺数(重复值多于两个)
> rank(c(2,2,2,2,2,3,4))
[1] 3 3 3 3 3 6 7 #没有1、2、4、5,并且3出现了5次
> rank(c(1,2,2,3))
[1] 1.0 2.5 2.5 4.0 #出现小数
对应到刚才的问题,可能是如下情况,利用rank(carat) <=2
分别找出3行、1行、0行记录:
> rank(c(1,1,1,2))
[1] 2 2 2 4
> rank(c(1,2,2,2))
[1] 1 3 3 3
> rank(c(2,2,2,2,2,3))
[1] 3 3 3 3 3 6
那么问题来了,到底应该怎么修改才能求出升序的前两个数,这是我的想法:
> ddply(diamonds,.(color),subset,carat <= sort(carat)[2])
carat cut color clarity depth table price x y z
1 0.20 Ideal D VS2 61.5 57 367 3.81 3.77 2.33
2 0.20 Premium D VS2 62.3 60 367 3.73 3.68 2.31
3 0.20 Premium D VS2 61.7 60 367 3.77 3.72 2.31
4 0.20 Premium E SI2 60.2 62 345 3.79 3.75 2.27
5 0.20 Premium E VS2 59.8 62 367 3.79 3.77 2.26
6 0.20 Premium E VS2 59.0 60 367 3.81 3.78 2.24
7 0.20 Premium E VS2 61.1 59 367 3.81 3.78 2.32
8 0.20 Premium E VS2 59.7 62 367 3.84 3.80 2.28
9 0.20 Ideal E VS2 59.7 55 367 3.86 3.84 2.30
10 0.20 Very Good E VS2 63.4 59 367 3.74 3.71 2.36
11 0.20 Ideal E VS2 62.2 57 367 3.76 3.73 2.33
12 0.22 Premium F SI1 60.4 61 342 3.88 3.84 2.33
13 0.20 Premium F VS2 62.6 59 367 3.73 3.71 2.33
14 0.22 Premium F SI1 61.7 60 470 3.90 3.85 2.39
......
有一点瑕疵,不能控制输出行数。
如果你有更好的解决方法,欢迎留言!
网友评论