加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

r语言 apply,lapply,tapply,sapply函数的使用

(2014-01-16 16:30:16)

R Library: Advanced functions

The R program (as a text file) for the code on this page.
In order to see more than just the results from the computations of the functions (i.e. if you want to see the functions echoed back in console as they are processed) use the echo=T option in the source function when running the program.

One of the main methods for improving the efficiency of a function is to avoid using loops which are very slow and inefficient. On this page we will show a number of ways to avoid using loops by vectorizing the functions. We will cover the following topics:

The apply function
The lapply function
The sapply function
The tapply function
The sweep function
The column functions
The row functions
Miscellaneous

The apply function

Applies a function to sections of an array and returns the results in an array.

apply(array, margin, function, ...)

Note that an array in R is a very generic data type; it is a general structure of up to eight dimensions. For specific dimesions there are special names for the structures. A zero dimensional array is a scalar or a point; a one dimensional array is a vector; and a two dimensional array is a matrix.
The margin argument is used to specify which margin we want to apply the function to and which margin we wish to keep. If the array we are using is a matrix then we can specify the margin to be either 1 (apply the function to the rows) or 2 (apply the function to the columns). The function can be any function that is built in or user defined. The ... after the function refers to any other arguments that is passed to the function being used.
Note that in R the apply function internally uses a loop so perhaps one of the other apply functions would be a better choice if time and efficiency is very important.

mat1 <- matrix(rep(seq(4), 4), ncol = 4)
mat1
     [,1] [,2] [,3] [,4] 
[1,]    1    1    1    1
[2,]    2    2    2    2
[3,]    3    3    3    3
[4,]    4    4    4    4

#row sums of mat1
apply(mat1, 1, sum)
[1]  4  8 12 16

#column sums of mat1
apply(mat1, 2, sum)
[1] 10 10 10 10
#using a user defined function
sum.plus.2 <- function(x){
        sum(x) + 2
}

#using the sum.plus.2 function on the rows of mat1
apply(mat1, 1, sum.plus.2)
[1]  6 10 14 18

#the function can be defined inside the apply function
#note the lack of curly brackets 
apply(mat1, 1, function(x) sum(x) + 2)
[1]  6 10 14 18
#generalizing the function to add any number to the sum
#add 3 to the row sums 
apply(mat1, 1, function(x, y) sum(x) + y, y=3)
[1]  7 11 15 19

#add 5 to the column sums
apply(mat1, 2, function(x, y) sum(x) + y, y=5)
[1] 15 15 15 15

The lapply function

Applies a function to elements in a list or a vector and returns the results in a list.

lapply(list, function, ...)

The lapply function becomes especially useful when dealing with data frames. In R the data frame is considered a list and the variables in the data frame are the elements of the list. We can therefore apply a function to all the variables in a data frame by using the lapply function.
Note that unlike in the apply function there is no margin argument since we are just applying the function to each component of the list.

#creating a data frame using mat1
mat1.df <- data.frame(mat1)
mat1.df
  X1 X2 X3 X4
1  1  1  1  1
2  2  2  2  2
3  3  3  3  3
4  4  4  4  4

#in the data frame mat1.df the variables mat1.1 - mat1.4 are elements of the list mat1.df
#these variables can thus be accessed by lapply
is.list(mat1.df)
[1] TRUE

#obtaining the sum of each variable in mat1.df
lapply(mat1.df, sum)
$X1
[1] 10

$X2
[1] 10

$X3
[1] 10

$X4
[1] 10

Verifying that the results are stored in a list, obtaining the names of the elements in the result list and displaying the first element of the result list.

#storing the results of the lapply function in the list y
y <- lapply(mat1.df, sum)

#verifying that y is a list
is.list(y)
[1] TRUE

#names of the elements in y
names(y)
[1] "X1" "X2" "X3" "X4"

#displaying the first element
y[[1]]
[1] 10

y$X1
[1] 10

Just like in the apply function we can use any built in or user defined function and we can define the function to be used inside the lapply function.

#user defined function with multiple arguments 
#function defined inside the lapply function
#displaying the first two results in the list
y1 <- lapply(mat1.df, function(x, y) sum(x) + y, y = 5)
y1[1:2]
$X1
[1] 15

$X2
[1] 15

Another useful application of the lapply function is with a "dummy sequence". The list argument is the dummy sequence and it is only used to specify how many iterations we would like to have the function executed. When the lapply functions is used in this way it can replace a for loop very easily.

#using the lapply function instead of the for loop
unlist(lapply(1:5, function(i) print(i) ))
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 1 2 3 4 5

#using the for loop
for(i in 1:5) print(i)
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

The sapply function

Applies a function to elements in a list and returns the results in a vector, matrix or a list.

sapply(list, function, ..., simplify)

When the argument simplify=F then the sapply function returns the results in a list just like the lapply function. However, when the argument simplify=T, the default, then the sapply function returns the results in a simplified form if at all possible. If the results are all scalars then sapply returns a vector. If the results are all of the same length then sapply will return a matrix with a column for each element in list to which function was applied.

y2 <- sapply(mat1.df, function(x, y) sum(x) + y, y = 5)
y2
X1 X2 X3 X4 
15 15 15 15 
     
is.vector(y2)
[1] TRUE

The tapply function

Applies a function to each cell of a ragged array.

tapply(array, indicies, function, ..., simplify)

The function is applied to each of the cells which are defined by the categorical variables listed in argument indicies. If the results of applying function to each cell is a single number then the results are returned in a multi-way array which has as many dimensions as there are components in the argument indicies. For example, if the argument indicies = c(gender, employed) then the result will be a 2 by 2 matrix with rows defined by male, female and columns defined by employed, unemployed. If the results are not a single value then the results are in a list with an dim attribute which means that it prints like a list but the user access the components by using subscripts like in an array.

#creating the data set with two categorical variables
x1 <- runif(16)
x1
 [1] 0.83189832 0.93558412 0.59623797 0.71544196 0.79925238 0.44859140
 [7] 0.03347409 0.62955913 0.97507841 0.71243195 0.58639700 0.43562781
[13] 0.23623549 0.97273216 0.72284040 0.25412129

cat1 <- rep(1:4, 4)
cat1
 [1] 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4

cat2 <- c(rep(1, 8), rep(2, 8))
cat2
 [1] 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2

mat2.df <- data.frame(x1)
names(mat2.df) <- c("x1")
mat2.df$cat1 <- cat1
mat2.df$cat2 <- cat2
mat2.df
          x1 cat1 cat2 
 1 0.9574315    1    1
 2 0.1163076    2    1
 3 0.6661923    3    1
 4 0.8265729    4    1
 5 0.6701039    1    1
 6 0.1478860    2    1
 7 0.8537499    3    1
 8 0.9993158    4    1
 9 0.4189768    1    2
10 0.8830733    2    2
11 0.6114867    3    2
12 0.3111015    4    2
13 0.8834808    1    2
14 0.3606836    2    2
15 0.7056246    3    2
16 0.8052925    4    2

tapply(mat2.df$x1, mat2.df$cat1, mean)
         1         2         3         4 
 0.7324982 0.3769876 0.7092634 0.7355707

tapply(mat2.df$x1, list(mat2.df$cat1, mat2.df$cat2), mean)
          1         2 
1 0.8137677 0.6512288
2 0.1320968 0.6218785
3 0.7599711 0.6585556
4 0.9129443 0.5581970

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有