R語言筆記1:初識數(shù)據(jù)結(jié)構(gòu)

簡介

R語言是一套開源的數(shù)據(jù)分析解決方案。R語言中提供了多種存儲數(shù)據(jù)的對象類型,包括標(biāo)量(R語言中的標(biāo)量是由向量的形式表示,可以說R語言沒有標(biāo)量),向量,矩陣,數(shù)組,數(shù)據(jù)框,列表還有因子(與前幾者并非完全獨(dú)立)。作為初學(xué)者,我主要關(guān)注這些結(jié)構(gòu)的三個(gè)方面:創(chuàng)建,取值,額外的問題。

1.“標(biāo)量”

所謂的標(biāo)量就是只含一個(gè)元素的向量,多用于儲存常量。示例如下:

> c <- 3
> c
[1] 3

可以看出來c是一個(gè)只存儲了1個(gè)元素的向量。

2.向量

向量是用于儲存數(shù)值型,字符型或者邏輯型的一維數(shù)組。數(shù)組中的值類型必須保持一致。最常見的創(chuàng)建向量的方式是通過函數(shù) : c( ) 。值得注意的是,R的下標(biāo)不從0開始而從1開始。

> #create a vector
> #vector(mode = "logical", length = 0)
> #c()
> v <- c(11,22,33,44,55,66)
> v
[1] 11 22 33 44 55 66

向量的創(chuàng)建

可以使用冒號生成數(shù)值序列來創(chuàng)建

> v <- c(1:5)
> v
[1]  1  2  3  4  5

也可以結(jié)合運(yùn)算表達(dá)式來創(chuàng)建

> v <- c(1:5*3)
> v
[1]  3  6  9 12 15

有趣的是,下面這種寫法的結(jié)果和上面的大相徑庭,不僅僅是數(shù)值的大小上,原因與運(yùn)算順序有關(guān),在此不再多敘。
v <- c(1:5**3)

獲取值的方式

通過下標(biāo)獲?。?/p>

> v[3]
[1] 9

通過c函數(shù)的下標(biāo)序列獲?。?/p>

> v[c(1,3,5)]
[1]  3  9 15

通過等值序列獲取:

> v[2:4]
[1]  6  9 12

通過c函數(shù)和等值序列獲?。?/p>

> v[c(1:3)]
[1] 3 6 9

也可以結(jié)合一些運(yùn)算獲得值,在此不一一列舉。

一些特殊情況

想要獲得下標(biāo)為0的元素不會報(bào)錯(cuò),不會返回值:

> v[0]
numeric(0)

越界也不會報(bào)錯(cuò),會返回NA(不存在的值):

> v[7]
[1] NA

使用等值序列的下標(biāo)獲得值時(shí)可以顛倒順序,而且不會報(bào)錯(cuò):

> v[7:2]
[1] NA NA 15 12  9  6

但是如果冒號左右缺失數(shù)據(jù)便會報(bào)錯(cuò):

#錯(cuò)誤的方式
v[3:]
v[:]
v[:2]

這些也是與Python的數(shù)組以及NumPy數(shù)組有區(qū)別的地方。

3.矩陣

矩陣其實(shí)是一個(gè)二維數(shù)組。一般創(chuàng)建格式為:
matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,dimnames = NULL)

矩陣的創(chuàng)建

可以使用數(shù)學(xué)表達(dá)式或者等值序列進(jìn)行創(chuàng)建。

> x <- matrix (1*2:11*2,nrow = 2)
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    4    8   12   16   20
[2,]    6   10   14   18   22

矩陣的創(chuàng)建默認(rèn)是按列填充,將矩陣創(chuàng)建函數(shù)中的參數(shù)設(shè)為byrow = TRUE便可按行填充。dimnames用于聲明行列名。參數(shù)位置不作要求。示例如下:

>  x <- matrix (1:10,nrow = 2,ncol =5,dimnames = list (c("R1","R2"),c("C1","C2","C3","C4","C5")),byrow =TRUE)  
> x
   C1 C2 C3 C4 C5
R1  1  2  3  4  5
R2  6  7  8  9 10

有趣的是,創(chuàng)建時(shí)規(guī)定了具體的nrow與ncol數(shù)值后如果實(shí)際傳入的數(shù)值數(shù)小于nrow * ncol,則會用傳入的值循環(huán)補(bǔ)上缺少的位置,但是會產(chǎn)生警告:

> x <- matrix (1*2:8*2,nrow = 2,ncol =5,dimnames = list (c("R1","R2"),c("C1","C2","C3","C4","C5")))  
Warning message:
In matrix(1 * 2:8 * 2, nrow = 2, ncol = 5, dimnames = list(c("R1",  :
  數(shù)據(jù)長度[7]不是矩陣行數(shù)[2]的整倍
> x
   C1 C2 C3 C4 C5
R1  4  8 12 16  6
R2  6 10 14  4  8

獲取值的方式

以該矩陣為例:

> x <- matrix (1:10,nrow = 2,dimnames = list (c("R1","R2"),c("C1","C2","C3","C4","C5")))  
> x
   C1 C2 C3 C4 C5
R1  1  3  5  7  9
R2  2  4  6  8 10

單下標(biāo)獲?。焊鶕?jù)所有數(shù)值中該值的位置獲取

x[2]
[1] 2

雙下標(biāo)獲取:根據(jù)二維坐標(biāo)獲取

> x[2,3]
[1] 6

結(jié)合c函數(shù)下標(biāo)序列:

> x[1,c(3,5)]
C3 C5 
 5  9 

結(jié)合等值序列:

> x[1,c(3:5)]
C3 C4 C5 
 5  7  9 

獲得行/列:

> x[1,]
C1 C2 C3 C4 C5 
 1  3  5  7  9 
> x[,3]
R1 R2 
 5  6 

一些特殊情況

同向量一樣,越界會用NA填補(bǔ),可以使用倒序等值序列,等值序列冒號兩端必須要有數(shù)字:

> x[11]
[1] NA
> x[11:2]
 [1] NA 10  9  8  7  6  5  4  3  2

如果雙下標(biāo)確定的二維坐標(biāo)實(shí)際不存在,則報(bào)錯(cuò)

> x[3,2]
Error in x[3, 2] : 下標(biāo)出界

4.數(shù)組

數(shù)組是可以在多維層次上存儲數(shù)據(jù)的對象??梢哉J(rèn)為是多維的矩陣。
array(data = NA, dim = length(data), dimnames = NULL)

數(shù)組的創(chuàng)建

使用array函數(shù)創(chuàng)建,data參數(shù)代表傳入的數(shù)據(jù),dim表示維度,dimnames為維度名稱。示例如下:

> dim1 <- c("A1","A2")
> dim2 <- c("B1","B2","B3")
> dim3 <- c("C1","C2","C3","C4")
> z <- array(1:24,c(2,3,4),dimnames = list(dim1,dim2,dim3))
> z
, , C1

   B1 B2 B3
A1  1  3  5
A2  2  4  6

, , C2

   B1 B2 B3
A1  7  9 11
A2  8 10 12

, , C3

   B1 B2 B3
A1 13 15 17
A2 14 16 18

, , C4

   B1 B2 B3
A1 19 21 23
A2 20 22 24

可以看出多維就是向量之間的組合,數(shù)值按行列填充,而且維度的層次是由里到外:2,3,4中2是行,3是列,4是外部的行。這與使用NumPy數(shù)組創(chuàng)建的矩陣以及部分語言中的利用數(shù)組創(chuàng)建的矩陣都有差別。
NumPy例子如下,可以看出有兩行,每行內(nèi)有三小行,四列:

>import numpy
>numpy.empty((2,3,4))
array([[[  3.10503618e+231,   1.29074048e-231,   2.20258734e-314,
           2.20282008e-314],
        [  2.20475013e-314,   2.20276932e-314,   2.20247903e-314,
           2.20272866e-314],
        [  2.20274681e-314,   2.20730875e-314,   2.20730883e-314,
           2.20250846e-314]],

       [[  2.20853208e-314,   2.20279100e-314,   2.20260412e-314,
           2.20320740e-314],
        [  2.20265303e-314,   2.20274598e-314,   2.20323984e-314,
           2.20250954e-314],
        [  2.20296227e-314,   2.20301979e-314,   2.22325913e-314,
           1.66880762e-308]]])

數(shù)組同矩陣一樣,也會循環(huán)補(bǔ)上缺失值:

> dim1 <- c("A1","A2")
> dim2 <- c("B1","B2","B3")
> dim3 <- c("C1","C2","C3","C4")
> z <- array(1:8,c(2,3,4),dimnames = list(dim1,dim2,dim3))
> z
, , C1

   B1 B2 B3
A1  1  3  5
A2  2  4  6

, , C2

   B1 B2 B3
A1  7  1  3
A2  8  2  4

, , C3

   B1 B2 B3
A1  5  7  1
A2  6  8  2

, , C4

   B1 B2 B3
A1  3  5  7
A2  4  6  8

獲取值的方式

下標(biāo)數(shù)等于維度數(shù)(使用第一個(gè)例子作為示范):

> z[1,2,3]
[1] 15

缺失不同的下標(biāo)可以獲得不同維度的組合:

> z[1,,]
   C1 C2 C3 C4
B1  1  7 13 19
B2  3  9 15 21
B3  5 11 17 23
> z[1,2,]
C1 C2 C3 C4 
 3  9 15 21 
> z[,2,]
   C1 C2 C3 C4
A1  3  9 15 21
A2  4 10 16 22
> z[,,]
, , C1

   B1 B2 B3
A1  1  3  5
A2  2  4  6

, , C2

   B1 B2 B3
A1  7  9 11
A2  8 10 12

, , C3

   B1 B2 B3
A1 13 15 17
A2 14 16 18

, , C4

   B1 B2 B3
A1 19 21 23
A2 20 22 24

但是下標(biāo)數(shù)目不對會報(bào)錯(cuò):

> z[1,2]
Error in z[1, 2] : 量度數(shù)目不對
> z[1,,,]
Error in z[1, , , ] : 量度數(shù)目不對
> z[,,,]
Error in z[, , , ] : 量度數(shù)目不對

結(jié)合表達(dá)式或運(yùn)算式:

> z[1,1:3,4]
B1 B2 B3 
19 21 23 
> z[1,c(1:3),4]
B1 B2 B3 
19 21 23 

5.數(shù)據(jù)框

數(shù)據(jù)框是表或者二維陣列狀結(jié)構(gòu),也被稱作表。其中每一列包含一個(gè)變量的值,并且每一行包含來自每一列的一組值。特點(diǎn)是列名非空,行名唯一,每列數(shù)據(jù)項(xiàng)個(gè)數(shù)相同。盡管每一列的模式必須唯一,但是數(shù)據(jù)框可以將不同模式的列組合在一起。
data.frame(..., row.names = NULL, check.rows = FALSE, check.names = TRUE, fix.empty.names = TRUE, stringsAsFactors = default.stringsAsFactors())

數(shù)據(jù)框的創(chuàng)建

> studentID <- c(1,2,3,4)
> age <- c(16,17,18,19)
> country <- c("China","USA","Canada","Japan")
> status <- c("Handsome","Poor","Smart","Poor")
> sd <- data.frame(studentID,age,country,status)
> sd
  studentID age country   status
1         1  16   China Handsome
2         2  17     USA     Poor
3         3  18  Canada    Smart
4         4  19   Japan     Poor

從這個(gè)簡單的例子可以看出來數(shù)據(jù)框可以認(rèn)為是含有相同個(gè)數(shù)數(shù)據(jù)項(xiàng)的向量的組合。check.rows與check.names等參數(shù)可以用來檢查不一致或重復(fù),詳情可以查看R文檔。

獲取值的方式

單下標(biāo)獲取某一列:

> sd[3]
  country
1   China
2     USA
3  Canada
4   Japan

雙下標(biāo)獲取單個(gè)數(shù)據(jù)項(xiàng):

> sd[1,2]
[1] 16

單等值序列獲取多列:

> sd[1:3]
  studentID age country
1         1  16   China
2         2  17     USA
3         3  18  Canada
4         4  19   Japan

雙等值序列獲取表的一部分:

> sd[1:3,2:4]
  age country   status
1  16   China Handsome
2  17     USA     Poor
3  18  Canada    Smart

取行/列/全部:

> sd[2,]
  studentID age country status
2         2  17     USA   Poor
> sd[,3]
[1] China  USA    Canada Japan 
Levels: Canada China Japan USA
> sd[,]
  studentID age country   status
1         1  16   China Handsome
2         2  17     USA     Poor
3         3  18  Canada    Smart
4         4  19   Japan     Poor

也可以使用 $ 取獲得某一列:

> sd$age
[1] 16 17 18 19

也可以結(jié)合c函數(shù):

> sd[c(1,2),c(3,4)]
  country   status
1   China Handsome
2     USA     Poor

額外的問題1:

關(guān)于多下標(biāo),有很多有趣的地方。這種表不是二維的嗎,多下標(biāo)取的是哪里的值呢?以上面的數(shù)據(jù)框?yàn)槔?,我們?shí)踐一下:
1.前兩個(gè)下標(biāo)是坐標(biāo)

> sd[1,2,0]
  age
1  16
> sd[1,2,1]
[1] 16
> sd[1,2,2]
[1] 16
> sd[1,2,3]
[1] 16
> sd[1,2,4]
[1] 16
> sd[1,2,5]
[1] 16
> sd[1,2,555]
[1] 16
> sd[1,2,-1]
[1] 16
> sd[1,2,-2]
[1] 16

前兩個(gè)下標(biāo)是坐標(biāo),第三個(gè)下標(biāo)取0時(shí)展示了該數(shù)值的行與列的位置,取非0的值時(shí)并無作用。

  1. 第一個(gè)和第三個(gè)數(shù)字是下標(biāo)
> sd[1,0,2]
data frame with 0 columns and 1 row
> sd[1,1,2]
[1] 1

顯然,R還是把前兩個(gè)當(dāng)成是二維坐標(biāo),最后的2并無作用。

> sd[1,-1,2]
$age
[1] 16

$country
[1] China
Levels: Canada China Japan USA

$status
[1] Handsome
Levels: Handsome Poor Smart

然而,這個(gè)輸出十分有意思。讓我們多實(shí)驗(yàn)幾個(gè)數(shù)字。

> sd[1,-1,1]
$age
[1] 16

$country
[1] China
Levels: Canada China Japan USA

$status
[1] Handsome
Levels: Handsome Poor Smart

> sd[1,-1,-1]
$age
[1] 16

$country
[1] China
Levels: Canada China Japan USA

$status
[1] Handsome
Levels: Handsome Poor Smart

> sd[2,-1,2]
$age
[1] 17

$country
[1] USA
Levels: Canada China Japan USA

$status
[1] Poor
Levels: Handsome Poor Smart

> sd[2,-2,3]
$studentID
[1] 2

$country
[1] USA
Levels: Canada China Japan USA

$status
[1] Poor
Levels: Handsome Poor Smart

> sd[-1,2,]
[1] 17 18 19
> sd[-1,3,4]
[1] USA    Canada Japan 
Levels: Canada China Japan USA

> sd[-2,-1,3]
  age country   status
1  16   China Handsome
3  18  Canada    Smart
4  19   Japan     Poor
> sd[-2,-2,3]
  studentID country   status
1         1   China Handsome
3         3  Canada    Smart
4         4   Japan     Poor

可以看出來第三個(gè)下標(biāo)完全沒有用。。
第一個(gè)下標(biāo)為x(正),第二個(gè)下標(biāo)為y(負(fù))時(shí),會展示出第x行除去第y列屬性的所有數(shù)值項(xiàng)。
第一個(gè)下標(biāo)為x(負(fù)),第二個(gè)下標(biāo)為y(正)時(shí),會展示出第y列除去第x行屬性的所有數(shù)值項(xiàng)。
第一個(gè)下標(biāo)為x(負(fù)),第二個(gè)下標(biāo)為y(負(fù))時(shí),會展示出整個(gè)表除去第x行以及第y列屬性的所有數(shù)值項(xiàng)。
最后,四個(gè)下標(biāo)會報(bào)錯(cuò)。

> sd[,,,,]
Error in `[.data.frame`(sd, , , , , ) : 參數(shù)沒有用(, )
  1. 越界問題
    僅當(dāng)單下標(biāo)越界時(shí)會報(bào)錯(cuò)。雙下標(biāo)取值越界會返回NULL,和前面的數(shù)據(jù)結(jié)構(gòu)返回NA不太一樣。
> sd[0]
data frame with 0 columns and 4 rows
> sd[7]
Error in `[.data.frame`(sd, 7) : undefined columns selected
> sd[1,6]
NULL

另外,前兩個(gè)下標(biāo)是負(fù)數(shù)且均絕對值越界時(shí),返回的是整個(gè)表(數(shù)據(jù)框)。
前兩個(gè)下標(biāo)是負(fù)數(shù)且前者絕對值越界時(shí),返回的是表除去后者絕對值列數(shù)的所有數(shù)據(jù)值。
前兩個(gè)下標(biāo)是負(fù)數(shù)且后者絕對值越界時(shí),返回的是表除去前者絕對值行數(shù)的所有數(shù)據(jù)值。

> sd[-6,-1]
  age country   status
1  16   China Handsome
2  17     USA     Poor
3  18  Canada    Smart
4  19   Japan     Poor
> sd[-5,-6]
  studentID age country   status
1         1  16   China Handsome
2         2  17     USA     Poor
3         3  18  Canada    Smart
4         4  19   Japan     Poor
> sd[-2,-7]
  studentID age country   status
1         1  16   China Handsome
3         3  18  Canada    Smart
4         4  19   Japan     Poor

語言表達(dá)不太好,大家可以自行理解。具體的原因等我參考R文檔后再補(bǔ)充。

額外的問題2:

  1. 綁定與解綁
    一直使用 $ 得到一列屬性是一種簡單但不簡潔的做法,可以使用attach函數(shù)進(jìn)行綁定操作。attach( ) 函數(shù)將數(shù)據(jù)框添加到R的搜索路徑中,R在遇到一個(gè)變量名后,將檢查搜索路徑中的數(shù)據(jù)框。
> attach(sd)
The following objects are masked _by_ .GlobalEnv:

    age, country, status, studentID

> summary(age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.00   16.75   17.50   17.50   18.25   19.00 
> plot(studentID,age)
> detach(sd)

在上面這個(gè)例子中,綁定了sd后,summary函數(shù)使用的age就是特指sd中的age列。
detach( )將數(shù)據(jù)框從搜索路徑中移除,可以省略,但使用它是一種好的習(xí)慣。(來也匆匆,去也沖沖)

  1. with函數(shù)
    attach有兩個(gè)不太令人滿意的地方:假如環(huán)境中已經(jīng)有了一個(gè)名為age的對象,原始對象會取得優(yōu)先權(quán),綁定并沒有實(shí)際效果;多層的綁定/解綁會使結(jié)構(gòu)難以處理。
    with函數(shù)中{ }結(jié)構(gòu)里所有的語句都只針對其中的數(shù)據(jù)框執(zhí)行,無需擔(dān)心名稱沖突,賦值也同樣如此,在結(jié)構(gòu)體外不起作用,但是可以使用 <<-將對象保存在全局變量中。
> with(sd,{
+     info1 <- summary(age)
+     info2 <<- summary(age)
+     info1
+ })
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.00   16.75   17.50   17.50   18.25   19.00 

> info1
錯(cuò)誤: 找不到對象'info1'
> info2
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.00   16.75   17.50   17.50   18.25   19.00 

6.列表

列表包括不同類型的元素和對象,是他們的有序集合。
為什么要學(xué)會使用列表:

  • 許多R語言函數(shù)默認(rèn)返回列表類型的對象。
  • 列表允許使用一種簡單的方式組織和重新調(diào)試不想干的信息。

列表的創(chuàng)建:

由下面的例子可以看出列表就是不同成分見的有序組合。

> a <- c(1,2,3,4)
> b <- c("Type1","Type2","Type3")
> c <- matrix(1:10,nrow = 5)
> d <- "Come on boy"
> l <- list(a,b,c,d)
> l
[[1]]
[1] 1 2 3 4

[[2]]
[1] "Type1" "Type2" "Type3"

[[3]]
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

[[4]]
[1] "Come on boy"

可以指明不同成分的名稱,通過成分名訪問數(shù)據(jù)。如果成分名是數(shù)字,需要加上引號,也就是說R認(rèn)為成分名必須是字符串。

> a <- c(1,2,3,4)
> b <- c("Type1","Type2","Type3")
> c <- matrix(1:10,nrow = 5)
> d <- "Come on boy"
> l <- list(number = a,data =b,c,d)
> l
$number
[1] 1 2 3 4

$data
[1] "Type1" "Type2" "Type3"

[[3]]
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

[[4]]
[1] "Come on boy"

上面的例子中,number成分存在一個(gè)對象,在列表中編號是 1,data成分存在一個(gè)對象,在列表中編號是2,編號3,4者無顯式成分名。
個(gè)人認(rèn)為成分名盡量與數(shù)據(jù)對象一對一,不建議以下這種形式:
l <- list(age =a,data =c(b,c,d))
列表的其他創(chuàng)建函數(shù)可見R文檔。

獲取值的方式:

通過單下標(biāo)獲?。?/p>

> l[1]
$number
[1] 1 2 3 4

> l[4]
[[1]]
[1] "Come on boy"

> l[]
$number
[1] 1 2 3 4

$data
[1] "Type1" "Type2" "Type3"

[[3]]
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

[[4]]
[1] "Come on boy"


結(jié)合表達(dá)式:

> l[1:3]
$number
[1] 1 2 3 4

$data
[1] "Type1" "Type2" "Type3"

[[3]]
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

> l[c(2,4)]
$data
[1] "Type1" "Type2" "Type3"

[[2]]
[1] "Come on boy"

通過成分名:
成分名作為下標(biāo)中需要加上引號。

> l[data]
Error in l[data] : 類別為'closure'的下標(biāo)不對
> l["data"]
$data
[1] "Type1" "Type2" "Type3"

> l$number
[1] 1 2 3 4

額外的問題:

除了0下標(biāo)外不存在的數(shù)值項(xiàng)會視為NA:

> l[0]
named list()
> l[7]
$<NA>
NULL

> l["HI"]
$<NA>
NULL

還有一些奇怪的東西大家可以來總結(jié)以下

> l[][2]
$data
[1] "Type1" "Type2" "Type3"

> l[][2][]
$data
[1] "Type1" "Type2" "Type3"

> l[][2][][1]
$data
[1] "Type1" "Type2" "Type3"

文中出現(xiàn)的部分函數(shù)說明

以下為R文檔簡述

  • summary( ):summary is a generic function used to produce result summaries of the results of various model fitting functions. The function invokes particular methods which depend on the class of the first argument.
  • str( ):Compactly display the internal structure of an R object, a diagnostic function and an alternative to summary (and to some extent). Ideally, only one line for each ‘basic’ structure is displayed. It is especially well suited to compactly display the (abbreviated) contents of (possibly nested) lists. The idea is to give reasonable output for any R object. It calls args for (non-primitive) function objects.

參考及引用資料

本人不會將以下資料用于商業(yè)用途并對其于自己的幫助表示由衷的感謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容