顯示具有 apply 標籤的文章。 顯示所有文章
顯示具有 apply 標籤的文章。 顯示所有文章

2022年2月4日 星期五

R資料框操作20技巧 (20 Tips for data.frame)

主題:

R語言中資料框的處理是重要技術之一,本篇文章說明資料框的常用處理技巧。



關鍵字:

  • 列(Row),行(Column)篩選
  • 類別 class
  • 維度 dim
  • 列名稱 row.names
  • 行可稱 colnames, names
  • 結構 str
  • 摘要 summary
  • 屬性 attributes
  • apply
  • lapply
資料框操作20技巧:

> # 技巧1 篩選行,結果為 vector

> iris$Sepal.Length

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1 

...

> # 技巧2 篩選行,結果為 vector(二個單引號)

> iris[, 'Sepal.Length']

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1

...

> # 技巧3 篩選行,結果為 vector(二個雙單引號)

> iris[, "Sepal.Length"]

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1

...

> # 技巧4 篩選行,結果為 vector

> iris[, 1]

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1

...

> # 技巧5 篩選行,結果為 vector

> iris[['Sepal.Length']]

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1

...

> # 技巧6 篩選行,結果為 vector

> iris[["Sepal.Length"]]

  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9

 [11] 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1

...

> # 技巧7 篩選行,結果為 data.frame

> iris['Sepal.Length']

    Sepal.Length

1            5.1

2            4.9

3            4.7

...

> # 技巧8 篩選行,結果為 data.frame

> iris["Sepal.Length"]

    Sepal.Length

1            5.1

2            4.9

3            4.7

...

> # 技巧9 篩選列,結果為 data.frame

> iris[1, ]

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species

1          5.1         3.5          1.4         0.2  setosa

> # 技巧10 篩選列,使用數值轉換,再加數值1,省略as.numeric會有錯誤

> as.numeric(iris[1,-5]) + 1

[1] 6.1 4.5 2.4 1.2

> # 技巧11 類別

> class(iris)

[1] "data.frame"

> # 技巧12 維度,結果為150列,5行

> dim(iris)

[1] 150   5

> # 技巧13 列名稱

> row.names(iris)

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

...

> # 技巧14 行名稱

> colnames(iris)

[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"     

> # 技巧15 行名稱

> names(iris)

[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"     

> # 技巧16 資料結構

> str(iris)

'data.frame': 150 obs. of  5 variables:

 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...

 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...

 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...

 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...

 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 ...

> # 技巧17 資料摘要

> summary(iris)

  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  

 Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100   setosa    :50  

 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300   versicolor:50  

 Median :5.800   Median :3.000   Median :4.350   Median :1.300   virginica :50  

 Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199                  

 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800                  

 Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500                  

> # 技巧18 資料屬性

> attributes(iris)

$names

[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"     

$class

[1] "data.frame"

$row.names

  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20

 [21]  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40

> # 技巧19 各列或各行群組計算

> apply(iris[-5], 1, mean)

  [1] 2.550 2.375 2.350 2.350 2.550 2.850 2.425 2.525 2.225

 [10] 2.400 2.700 2.500 2.325 2.125 2.800 3.000 2.750 2.575

...

> # 技巧20 各行群組計算,回傳結果為串列(list)- lapply 以行運算為主

> lapply(iris[-5], mean)

$Sepal.Length

[1] 5.843333

$Sepal.Width

[1] 3.057333

$Petal.Length

[1] 3.758

$Petal.Width

[1] 1.199333

# end

2017年7月26日 星期三

函數原始碼 source code

R是開放原始碼軟體, 以下說明查詢函數的原始碼的方法(參考 1, 2).

簡介

R函數許多原始檔案包括 C, Fortran等程式碼, 常用呼叫其他已編譯完成程式的函數包括: .C .Call, .Fortran, .External, .Internal, .Primitive 等函數. (參考3  R Internals, 2017).

C程式在編譯成R時,可直接經由 primitives(原生) 或 .Internal interface (.內部介面)來呼叫使用, 此方式與 .External interface (.外部介面)類似, 但使用語法不相同.

「.Internal」 和 「.Primitive」 一般用於呼叫 C 的介面:
  • .Internal 是標準的用法,在呼叫C之前可以檢查R程式碼中的參數 .
  • .Primitive 執行效能較高,但不允許在函數中使用R程式.
R的原始碼 R-3.4.1.tar.gz (參考4) 解壓縮之後在 \R-3.4.1.tar\R-3.4.1\src\main 目錄中存放約121個 *.c 原始碼.



查詢函數原始碼

# 1
使用 pryr 套件的 ftype 函數可檢視該函數的種類:

  • regular/primitive/internal function
  • internal/S3/S4 generic
  • S3/S4/RC method

    library(pryr)
    ftype(apply) # "function"

    # 2
    直接輸入函數名稱, 即可顯示原始檔.

    apply



    # 3
    在 RStuido 軟體的程式編輯視窗, 選取 apply , 按 CTRL +  滑鼠左鍵, 可開啟原始檔.



    #4
    getAnywhere {utils} 可查詢函數隸屬於哪些套件與內容. 使用 show_c_source {pryr}可檢視該函數原始檔.




    #5
    使用 methods 函數與 getAnywhere 函數.


    R程式碼


    library(pryr)
    ftype(apply) # "function"
    apply
    
    lapply
    ftype(lapply) # "internal"
    getAnywhere(lapply)
    show_c_source(.Primitive(lapply(x)))
    
    princomp
    ftype(princomp) # "s3" "generic"
    methods(princomp)
    getAnywhere(princomp.default)
    # end

    參考資料

    [1] https://stackoverflow.com/questions/19226816/how-can-i-view-the-source-code-for-a-function

    [2] https://stackoverflow.com/questions/3485228/view-source-code-in-r

    [3] R Core Team, R Internals - Version 3.4.1 (2017-06-30), URL:  https://cran.r-project.org/doc/manuals/r-release/R-ints.pdf.

    [4] R 原始碼, https://cran.r-project.org/src/base/R-3/R-3.4.1.tar.gz

    2016年8月22日 星期一

    矩陣的條件式篩選

    Problem:


    在R的資料處理環境中,有時須先篩選符合條件的資料,再進行後續處理,以下說明如何完成此需求.

    感謝R友-Mimi 提供此問題.

    Analysis:
























    本問題是如何找出同時滿足數值大於或等於0.5, 較辛苦的方法是將所有條件用 AND 運算(&)找出其結果. 實務上可考慮邏輯運算特性, 即 TRUE 表示1, FALSE 表示0, 利用 sum( )函數計算加總為12表示該列所有行滿足條件. 因為是每列都要判斷, 因此採用 apply, 第2個參數設定為1表示列運算. 最後以 which 回傳符合條件之指標.











    # R code
    # 建立矩陣範例 318*12
    set.seed(123)
    m <- matrix(round(c(runif(318*7), rep(1, 318*5)), 2), ncol=12)
    rownames(m) <- paste0("row", 1:318)
    head(m)

    # 條件篩選
    m.check <- (m >= 0.5)
    head(m.check)

    # 如果整列加總=12,表示所該列所有資料行皆符合篩選條件
    ind <- which(apply(m.check, 1, sum) == 12)
    ind
    m[ind, ]
    # end