【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 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章