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

加载中…