【R】向量下标和子集

正整数下标

对向量x, 在后面加方括号和下标可以访问向量的元素和子集。

设x <- c(1, 4, 6.25)。 x[2]取出第二个元素; x[2] <- 99修改第二个元素。 x[c(1,3)]取出第1、3号元素; x[c(1,3)] <- c(11, 13)修改第1、3号元素。 下标可重复。 例如

> x <- c(1, 4, 6.25)
> x[2]
## [1] 4

> x[2] <- 99; x
## [1]  1.00 99.00  6.25

> x[c(1,3)]
## [1] 1.00 6.25

> x[c(1,3)] <- c(11, 13); x
## [1] 11 99 13

> x[c(1,3,1)]
## [1] 11 13 11

负整数下标

负下标表示扣除相应的元素后的子集,如

> x <- c(1,4,6.25)
> x[-2]
## [1] 1.00 6.25
> x[-c(1,3)]
## [1] 4

负整数下标不能与正整数下标同时用来从某一向量中取子集, 比如,x[c(1,-2)]没有意义。

空下标与零下标

x[]表示取x的全部元素作为子集。 这与x本身不同,比如

> x <- c(1,4,6.25)
> x[] <- 999
> x
## [1] 999 999 999

> x <- c(1,4,6.25)
> x <- 999
> x
## [1] 999

x[0]是一种少见的做法, 结果返回类型相同、长度为零的向量, 如numeric(0)。 相当于空集。

当与正整数下标一起使用时会被忽略。 当0与负整数下标一起使用时也会被忽略。

下标超界

设向量x长度为, 则使用正整数下标时下标应在中取值。 如果使用大于的下标, 读取时返回缺失值,并不出错。 给超出的下标元素赋值, 则向量自动变长, 中间没有赋值的元素为缺失值。 例如

> x <- c(1,4,6.25)
> x[5]
## [1] NA

> x
## [1] 1.00 4.00 6.25

> x[5] <- 9
> x
## [1] 1.00 4.00 6.25   NA 9.00

虽然R的语法对下标超界不视作错误, 但是这样的做法往往来自不良的程序思路, 而且对程序效率有影响, 所以实际编程中应避免下标超界。

逻辑下标

下标可以是与向量等长的逻辑表达式, 一般是关于本向量或者与本向量等长的其它向量的比较结果,如

x <- c(1,4,6.25)
x[x > 3]
## [1] 4.00 6.25

取出x的大于3的元素组成的子集。

要注意的是,如果逻辑下标中有缺失值, 对应结果也是缺失值。 所以,在用逻辑下标作子集选择时, 一定要考虑到缺失值问题。正确的做法是加上!is.na前提, 如

> x <- c(1, 4, 6.25, NA)
> x[x > 2]
## [1] 4.00 6.25   NA

> x[!is.na(x) & x > 2]
## [1] 4.00 6.25

which()、which.min()、which.max()函数

函数which()可以用来找到满足条件的下标, 如

> x <- c(3, 4, 3, 5, 7, 5, 9)
> which(x > 5)
## [1] 5 7

> seq(along=x)[x > 5]
## [1] 5 7

这里seq(along=x)会生成由x的下标组成的向量。 用which.min()、which.max求最小值的下标和最大值的下标, 不唯一时只取第一个。如

> which.min(x)
## [1] 1

> which.max(x)
## [1] 7

元素名

向量可以为每个元素命名。如

> ages <- c("李明"=25,"田晓霞"=21,"孙少平"=22)
> ages
## 李明 田晓霞 孙少平 
    25     21     22

或者

> ages <- c(25,21,22)
> names(ages)<- c("李明","田晓霞","孙少平")
> ages
## 李明 田晓霞 孙少平 
    25     21     22 

或者

> ages <- setNames(c(25,21,22),c("李明","田晓霞","孙少平"))
> ages
## 李明 田晓霞 孙少平 
    25     21     22 

这时可以用元素名或元素名向量作为向量的下标,如

> ages["李明"]
## 李明 
  25

> ages["李明"] <- 11
> ages
## 李明 田晓霞 孙少平 
    11     21     22 

这实际上建立了字符串到数值的映射表。

用字符串作为下标时, 如果该字符串不在向量的元素名中, 读取时返回缺失值结果, 赋值时该向量会增加一个元素并以该字符串为元素名。

带有元素名的向量也可以是字符型或其它基本类型,如

> sex <- c("孙少平"="男","田晓霞"="女")
> sex
## 孙少平 田晓霞 
  "男"   "女" 

除了给向量元素命名外, 在矩阵和数据框中还可以给行、列命名, 这会使得程序的扩展更为容易和安全。

R允许仅给部分元素命名, 这时其它元素名字为空字符串。 不同元素的元素名一般应该是不同的, 否则在使用元素作为下标时会发生误读, 但是R语法允许存在重名。

用unname(x)返回去掉了元素名的x的副本, 用names(x) <- NULL可以去掉x的元素

> unname(ages)
## [1] 11 21 22

> ages
## 李明 田晓霞 孙少平 
    11     21     22 

> names(ages) <- NULL
> ages
## [1] 11 21 22

用R向量下标作映射

R在使用整数作为向量下标时,允许使用重复下标, 这样可以把数组x看成一个的整数到 x[1], x[2], , x[n]的一个映射表, 其中是x的长度。 比如,某商店有三种礼品,编号为1,2,3, 价格分别为68, 88和168。令

> price.map <- c(68, 88, 168)

设某个收银员在一天内分别售出礼品编号为3,2,1,1,2,2,3, 可以用如下的映射方式获得售出的这些礼品对应的价格:

> items <- c(3,2,1,1,2,2,3)
> y <- price.map[items]; print(y)
## [1] 168  88  68  68  88  88 168

R向量可以用字符型向量作下标, 字符型下标也允许重复, 所以可以把带有元素名的R向量看成是元素名到元素值的映射表。 比如,设sex为10个学生的性别(男、女)

> sex <- c("男", "男", "女", "女", "男", "女", "女", "女", "女", "男")

希望把每个学生按照性别分别对应到蓝色和红色。 首先建立一个R向量当作映射

> sex.color <- c("男"="blue", "女"="red")

用R向量sex.color当作映射,可以获得每个学生对应的颜色

> cols <- sex.color[sex]; print(cols)
##     男     男     女     女     男     女     女     女     女     男 
## "blue" "blue"  "red"  "red" "blue"  "red"  "red"  "red"  "red" "blue"

这样的映射结果中带有不必要的元素名, 用unname()函数可以去掉元素名,如

> unname(cols)
##  [1] "blue" "blue" "red"  "red"  "blue" "red"  "red"  "red"  "red"  "blue"

集合运算

可以把向量x看成一个集合,但是其中的元素允许有重复。 用unique(x)可以获得x的所有不同值。如

> unique(c(1, 5, 2, 5))
## [1] 1 5 2

用a %in% x判断a的每个元素是否属于向量x,如

> 5 %in% c(1,5,2)
## [1] TRUE

> c(5,6) %in% c(1,5,2)
## [1]  TRUE FALSE

与%in运算符类似, 函数match(x, table)对向量x的每个元素, 从向量table中查找其首次出现位置并返回这些位置。 没有匹配到的元素位置返回NA_integer_(整数型缺失值)。 如

> match(5, c(1,5,2))
## [1] 2

> match(5, c(1,5,2,5))
## [1] 2

> match(c(2,5), c(1,5,2,5))
## [1] 3 2

> match(c(2,5,0), c(1,5,2,5))
## [1]  3  2 NA

用intersect(x,y)求交集,结果中不含重复元素,如

> intersect(c(5, 7), c(1, 5, 2, 5))
## [1] 5

用union(x,y)求并集,结果中不含重复元素,如

> union(c(5, 7), c(1, 5, 2, 5))
## [1] 5 7 1 2

用setdiff(x,y)求差集,即x的元素中不属于y的元素组成的集合, 结果中不含重复元素,如

> setdiff(c(5, 7), c(1, 5, 2, 5))
## [1] 7

用setequal(x,y)判断两个集合是否相等, 不受次序与重复元素的影响,如

> setequal(c(1,5,2), c(2,5,1))
## [1] TRUE

> setequal(c(1,5,2), c(2,5,1,5))
## [1] TRUE

练习

设文件class.csv内容如下:

name,sex,age,height,weight
Alice,F,13,56.5,84
Becka,F,13,65.3,98
Gail,F,14,64.3,90
Karen,F,12,56.3,77
Kathy,F,12,59.8,84.5
Mary,F,15,66.5,112
Sandy,F,11,51.3,50.5
Sharon,F,15,62.5,112.5
Tammy,F,14,62.8,102.5
Alfred,M,14,69,112.5
Duke,M,14,63.5,102.5
Guido,M,15,67,133
James,M,12,57.3,83
Jeffrey,M,13,62.5,84
John,M,12,59,99.5
Philip,M,16,72,150
Robert,M,12,64.8,128
Thomas,M,11,57.5,85
William,M,15,66.5,112

用如下程序可以把上述文件读入为R数据框d.class, 并取出其中的name和age列到变量name和age中:

> d.class <- read.csv("class.csv", header=TRUE, stringsAsFactors=FALSE)
> name <- d.class[,"name"]
> age <- d.class[,"age"]
> age
 [1] 13 13 14 12 12 15 11 15 14 14 14 15 12 13 12 16 12 11 15
> d.class
      name sex age height weight
1    Alice   F  13   56.5   84.0
2    Becka   F  13   65.3   98.0
3     Gail   F  14   64.3   90.0
4    Karen   F  12   56.3   77.0
5    Kathy   F  12   59.8   84.5
6     Mary   F  15   66.5  112.0
7    Sandy   F  11   51.3   50.5
8   Sharon   F  15   62.5  112.5
9    Tammy   F  14   62.8  102.5
10  Alfred   M  14   69.0  112.5
11    Duke   M  14   63.5  102.5
12   Guido   M  15   67.0  133.0
13   James   M  12   57.3   83.0
14 Jeffrey   M  13   62.5   84.0
15    John   M  12   59.0   99.5
16  Philip   M  16   72.0  150.0
17  Robert   M  12   64.8  128.0
18  Thomas   M  11   57.5   85.0
19 William   M  15   66.5  112.0
  1. 求出age中第3, 5, 7号的值;

     > age[c(3,5,7)]
     ## [1] 14 12 11
    
  2. 用变量age, 求出达到15岁及以上的那些值;

     > age[age>=15]
     ## [1] 15 15 15 16 15 
    
  3. 用变量name和age, 求出Mary与James的年龄。

     > set <- setNames(age,name)
     > set[match(c("Mary","James"),name)]
      Mary James 
        15    12 
    
  4. 求age中除Mary与James这两人之外的那些人的年龄值,保存到变量age1中。

    > a <- match(c("Mary","James"),name)
    > b <- (1:length(name))
    
    > a
    [1]  6 13
    > b
     [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
    
    > age1 <- set[setdiff(b,a)]
    > age1
      Alice   Becka    Gail   Karen   Kathy   Sandy  Sharon   Tammy  Alfred    Duke   Guido 
         13      13      14      12      12      11      15      14      14      14      15 
    Jeffrey    John  Philip  Robert  Thomas William 
         13      12      16      12      11      15 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345