this my first question and I hope to collaborate in the community.
I am in a project in which I must fill the NA values with the average of their neighbors from a matrix of ncol = 10 and nrow = 10. I have developed the following code however it is very computationally inefficient:
Code
get_neighbor <- function(matrix, x=1,y=1){
z <- complex(real = rep(1:nrow(matrix), ncol(matrix)),
imaginary = rep(1:ncol(matrix), each = nrow(matrix)))
lookup <- lapply(seq_along(z), function(x){
# calcular la distantancia
dist <- which(abs(z - z[x]) < 2)
# sacar el elemento x del vecindario
dist[which(dist != x)]
})
index <- (y-1)*(nrow(matrix))+x
matrix[lookup[[index]]]
}
nn_mean <- function(a){
if(sum(is.na(a))!=ncol(a)*nrow(a)){
C <- permutations(2, 2, c(1,dim(a)[1]), repeats.allowed = T)
Borders <- data.frame(matrix(data = 0, ncol = 2, nrow = nrow(a)*2 + ncol(a)*2 - 4))
Borders[1:nrow(a), 1] <- 1:nrow(a); Borders[1:nrow(a), 2] <- 1
for(i in 2:(ncol(a)-1)){
Borders[i + nrow(a) - 1, 2] <- i; Borders[i + 2*(nrow(a) - 1) - 1, 2] <- i
Borders[i + nrow(a) - 1, 1] <- 1; Borders[i + 2*(nrow(a) - 1) - 1, 1] <- nrow(a)
}
Borders[1:ncol(a) + 3*(nrow(a))-4, 2] <- ncol(a)
Borders[1:ncol(a) + 3*(nrow(a))-4, 1] <- 1:ncol(a)
id <- which(is.na(a), arr.ind = T)
id <- data.frame(cbind(id, rep(0, nrow(id))))
while(nrow(id)!=0){
for(i in 1:nrow(id)){
id[i,3] <- sum(is.na(get_neighbor(a, id[i, 1], id[i, 2])))
}
max_na <- max(id[, 3])
for(i in 1:(nrow(a)*2 + ncol(a)*2 - 4)){
if(is.na(a[Borders[i, 1], Borders[i, 2]]) & sum(is.na(get_neighbor(a, Borders[i, 1], Borders[i, 2]))) == 5){
index <- which(id[,1] == Borders[i, 1] & id[,2] == Borders[i, 2])
id[index, 3] <- max_na +1
}
}
for(i in 1:4){
if(is.na(a[C[i,1], C[i,2]]) & sum(is.na(get_neighbor(a, C[i, 1], C[i, 2]))) == 3){
index <- which(id[,1] == C[i, 1] & id[,2] == C[i, 2])
id[index, 3] <- max_na +1
}
}
id <- id[order(id[,3]),]
index <- which(id[,3]== min(id[,3]))
for(i in 1:length(index)){
a[id[i, 1], id[i, 2]] <- mean(get_neighbor(a, id[i, 1], id[i, 2]), na.rm = T)
if(is.nan(a[id[i, 1], id[i, 2]])){a[id[i, 1], id[i, 2]] <- NA}
}
#print(a)
id <- which(is.na(a), arr.ind = T)
id <- data.frame(cbind(id, rep(0, nrow(id))))
}
}
return(a)
}
example
a <- matrix(data = runif(100, 0, 10), ncol = 10, nrow = 10)
a[a<2] <- NA
a
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2.313512 NA 5.311104 2.832978 9.917106 2.734799 7.309386 NA 4.794476 6.479147
[2,] 8.855676 7.555101 8.369477 6.346744 7.727896 NA 9.019421 5.061894 9.116066 6.732293
[3,] 2.948539 7.440258 6.918414 2.155361 3.511407 5.601253 NA 6.561557 9.543535 4.082592
[4,] 8.455382 9.169974 NA 4.978224 6.202393 NA 9.435753 9.411371 NA 2.128417
[5,] 7.744456 3.333072 6.975128 5.876849 4.044768 2.948399 5.067653 NA 6.039412 7.350782
[6,] 8.793417 9.683755 8.053603 7.406450 6.348171 3.122946 9.378282 5.808363 7.923061 6.415419
[7,] 4.759612 3.431247 4.123641 6.899569 4.464683 6.588431 5.985248 7.962148 6.668238 4.503556
[8,] 5.992242 NA 7.099657 6.446650 NA 8.448873 5.884961 NA 2.209453 8.103988
[9,] 6.383036 NA NA 5.499157 6.972433 3.129470 3.284383 9.150565 8.484186 4.672878
[10,] NA NA 4.258936 NA 9.015525 NA NA NA NA 6.639832
nn_mean(a)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2.313512 6.480974 5.311104 2.832978 9.917106 2.734799 7.309386 7.060248 4.794476 6.479147
[2,] 8.855676 7.555101 8.369477 6.346744 7.727896 6.545895 9.019421 5.061894 9.116066 6.732293
[3,] 2.948539 7.440258 6.918414 2.155361 3.511407 5.601253 7.111993 6.561557 9.543535 4.082592
[4,] 8.455382 9.169974 5.855910 4.978224 6.202393 5.258804 9.435753 9.411371 6.587278 2.128417
[5,] 7.744456 3.333072 6.975128 5.876849 4.044768 2.948399 5.067653 7.580556 6.039412 7.350782
[6,] 8.793417 9.683755 8.053603 7.406450 6.348171 3.122946 9.378282 5.808363 7.923061 6.415419
[7,] 4.759612 3.431247 4.123641 6.899569 4.464683 6.588431 5.985248 7.962148 6.668238 4.503556
[8,] 5.992242 5.298239 7.099657 6.446650 6.056158 8.448873 5.884961 6.203648 2.209453 8.103988
[9,] 6.383036 5.902524 5.834195 5.499157 6.972433 3.129470 3.284383 9.150565 8.484186 4.672878
[10,] 6.383036 5.731883 4.258936 6.436513 9.015525 5.600453 5.291218 6.689444 7.236865 6.639832
some idea or a function that is efficient?
This can be written in a even short and fast way in R:
nn_impute <- function(dat){
idx <- which(is.na(dat), TRUE)
impute <- function(x){
y <- expand.grid(x[1] + c(-1,0,1), x[2] + c(-1,0,1))
z <- !(y == 0 | y > nrow(dat) | y> ncol(dat))
mean(dat[as.matrix(y[rowSums(z) == 2,])], na.rm = TRUE)
}
dat[idx] <- apply(idx, 1, impute)
dat
}
nn_impute(a) ## Returns the filled in values
This code is around 38X faster than the provided code
I kept your code above, apart from nn_mean function, I defined an nn_mean2 function.
It works about 20x times faster than yours, but gives different results. Since I don't know why you wrote your function the way you did, i.e. your requirements, I can't tell why my approach is not suitable. but it is way faster. It naively uses your get_neighbour definition, averages the found neighbour values and substitutes them into the holes. You must be needing to do something else or our results would have matched I would have thought.
Here it is for consideration
nn_mean2 <- function(a){
res2 <- a
# get the missings
list_of_missing <- which(is.na(a))
list_of_missing_df <- data.frame(which(is.na(a),arr.ind = TRUE))
list_of_missing_df$missing_fills <- purrr::map_dbl(seq_len(nrow(list_of_missing_df)),
~{
mean(get_neighbor(a,
x=list_of_missing_df$row[.x],
y=list_of_missing_df$col[.x]),
na.rm=TRUE)
})
res2[list_of_missing] <- list_of_missing_df$missing_fills
res2
}
res2 <- nn_mean2(a)
microbenchmark::microbenchmark(n1 = nn_mean(a),
n2=nn_mean2(a))
# A tibble: 2 x 13
expression min median `itr/sec` mem_al~1 gc/se~2 n_itr n_gc total~3 result memory
<bch:expr> <bch:tm> <bch:tm> <dbl> <bch:by> <dbl> <int> <dbl> <bch:t> <list> <list>
1 n1 380ms 425ms 2.35 107.34MB 4.71 2 4 850ms <NULL> <Rprofmem>
2 n2 17ms 20.1ms 39.9 6.91MB 5.99 20 3 501ms <NULL> <Rprofmem>
# see the difference in values though
res1 - res2
Related
I am using the lapp functin of {terra} in R and I want to update rast_a with values from rast_b or rast_c (and some other math) depending on the value in each cell of rast_a.
sample data
rast_a <- rast(ncol = 2, nrow = 2)
values(rast_a) <- 1:4
rast_b <- rast(ncol = 2, nrow = 2)
values(rast_b) <- c(2,2,2,2)
rast_c <- rast(ncol = 2, nrow = 2)
values(rast_c) <- c(3,3,3,3)
Problem
This is my (wrong) attempt.
my_update_formula <- function(a, b, c) {
a[a == 1] <- b[a == 1] + 10 + 20 - 30
a[a == 2] <- c[a == 2] + 10 + 50 - 50
return(a)
}
result <- lapp(c(rast_a, rast_b, rast_c),
fun = my_update_formula)
values(result)
lyr1
[1,] 3
[2,] 3
[3,] 3
[4,] 4
The actual result should be 2,3,3,4. But because of the operations inside the formula, the first value gets updated twice. First it is changed from 1 to 2 (correctly) but then it fulfills the condition of the second line of code also, and is changed again (I don't want that to happen).
How can I solve this please?
You can change your formula to
f1 <- function(a, b, c) {
d <- a
d[a == 1] <- b[a == 1]
d[a == 2] <- c[a == 2] + 10
d
}
#or
f2 <- function(a, b, c) {
i <- a == 1
j <- a == 2
a[i] <- b[i]
a[j] <- c[j] + 10
return(a)
}
lapp(c(rast_a, rast_b, rast_c), fun = f1) |> values()
# lyr1
#[1,] 2
#[2,] 13
#[3,] 3
#[4,] 4
lapp(c(rast_a, rast_b, rast_c), fun = f2) |> values()
# lyr1
#[1,] 2
#[2,] 13
#[3,] 3
#[4,] 4
You can get the same result with
x <- ifel(rast_a==1, rast_b,
ifel(rast_a == 2, rast_c + 10, rast_a))
How to extract the row and column of the element in use when using apply function? For example, say I want to apply a function for each element of the matrix where row and column number of the selected element are also variables in the function. A simple reproducible example is given below
mymatrix <- matrix(1:12, nrow=3, ncol=4)
I want a function which does the following
apply(mymatrix, c(1,2), function (x) sum(x, row_number, col_number))
where row_number and col_number are the row and column number of the selected element in mymatrix. Note that my function is more complicated than sum, so a robust solution is appreciated.
I'm not entirely sure what you're trying to do but I would use a for loop here.
Pre-allocate the return matrix and this will be very fast
ret <- mymatrix
for (i in 1:nrow(mymatrix))
for (j in 1:ncol(mymatrix))
ret[i, j] <- sum(mymatrix[i, j], i, j)
# [,1] [,2] [,3] [,4]
#[1,] 3 7 11 15
#[2,] 5 9 13 17
#[3,] 7 11 15 19
Benchmark analysis 1
I was curious so I ran a microbenchmark analysis to compare methods; I used a bigger 200x300 matrix.
mymatrix <- matrix(1:600, nrow = 200, ncol = 300)
library(microbenchmark)
res <- microbenchmark(
for_loop = {
ret <- mymatrix
for (i in 1:nrow(mymatrix))
for (j in 1:ncol(mymatrix))
ret[i, j] <- sum(mymatrix[i, j], i, j)
},
expand_grid_mapply = {
newResult<- mymatrix
grid1 <- expand.grid(1:nrow(mymatrix),1:ncol(mymatrix))
newResult[]<-
mapply(function(row_number, col_number){ sum(mymatrix[row_number, col_number], row_number, col_number) },row_number = grid1$Var1, col_number = grid1$Var2 )
},
expand_grid_apply = {
newResult<- mymatrix
grid1 <- expand.grid(1:nrow(mymatrix),1:ncol(mymatrix))
newResult[]<-
apply(grid1, 1, function(x){ sum(mymatrix[x[1], x[2]], x[1], x[2]) })
},
double_sapply = {
sapply(1:ncol(mymatrix), function (x) sapply(1:nrow(mymatrix), function (y) sum(mymatrix[y,x],x,y)))
}
)
res
#Unit: milliseconds
# expr min lq mean median uq max
# for_loop 41.42098 52.72281 56.86675 56.38992 59.1444 82.89455
# expand_grid_mapply 126.98982 161.79123 183.04251 182.80331 196.1476 332.94854
# expand_grid_apply 295.73234 354.11661 375.39308 375.39932 391.6888 562.59317
# double_sapply 91.80607 111.29787 120.66075 120.37219 126.0292 230.85411
library(ggplot2)
autoplot(res)
Benchmark analysis 2 (with expand.grid outside of microbenchmark)
grid1 <- expand.grid(1:nrow(mymatrix),1:ncol(mymatrix))
res <- microbenchmark(
for_loop = {
ret <- mymatrix
for (i in 1:nrow(mymatrix))
for (j in 1:ncol(mymatrix))
ret[i, j] <- sum(mymatrix[i, j], i, j)
},
expand_grid_mapply = {
newResult<- mymatrix
newResult[]<-
mapply(function(row_number, col_number){ sum(mymatrix[row_number, col_number], row_number, col_number) },row_number = grid1$Var1, col_number = grid1$Var2 )
},
expand_grid_apply = {
newResult<- mymatrix
newResult[]<-
apply(grid1, 1, function(x){ sum(mymatrix[x[1], x[2]], x[1], x[2]) })
}
)
res
#Unit: milliseconds
# expr min lq mean median uq max
# for_loop 39.65599 54.52077 60.87034 59.19354 66.64983 95.7890
# expand_grid_mapply 130.33573 167.68201 194.39764 186.82411 209.33490 400.9273
# expand_grid_apply 296.51983 373.41923 405.19549 403.36825 427.41728 597.6937
That's not how apply works: You cannot access the current index (row, col index) from inside [lsvm]?apply-family.
You will have to create the current row and col index before applying. ?expand.grid.
mymatrix <- matrix(1:12, nrow=3, ncol=4)
newResult<- mymatrix
grid1 <- expand.grid(1:nrow(mymatrix),1:ncol(mymatrix))
newResult[]<-
mapply(function(row_number, col_number){ sum(mymatrix[row_number, col_number], row_number, col_number) },row_number = grid1$Var1, col_number = grid1$Var2 )
newResult
# [,1] [,2] [,3] [,4]
#[1,] 3 7 11 15
#[2,] 5 9 13 17
#[3,] 7 11 15 19
If you want to use apply
newResult[]<-
apply(grid1, 1, function(x){ sum(mymatrix[x[1], x[2]], x[1], x[2]) })
This is my thought with outer() function.
The third argument FUN can be any two-argument function.
mymatrix <- matrix(1:12, nrow = 3, ncol = 4)
nr <- nrow(mymatrix)
nc <- ncol(mymatrix)
mymatrix + outer(1:nr, 1:nc, FUN = "+")
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 5 9 13 17
[3,] 7 11 15 19
With #Maurits Evers' benchmark code :
Unit: microseconds
expr min lq mean median uq max
for_loop 19963.203 22427.1630 25308.168 23811.855 25017.031 158341.678
outer 848.247 949.3515 1054.944 1011.457 1059.217 1463.956
In addition, I try to complete your original idea with apply(X, c(1,2), function (x)) :
(It's a little slower than other answers)
mymatrix <- matrix(1:12, nrow = 3, ncol = 4)
n <- 1 # n = index of data
nr <- nrow(mymatrix)
apply(mymatrix, c(1,2), function (x) {
row_number <- (n-1) %% nr + 1 # convert n to row number
col_number <- (n-1) %/% nr + 1 # convert n to column number
res <- sum(x, row_number, col_number)
n <<- n + 1
return(res)
})
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 5 9 13 17
[3,] 7 11 15 19
I would like to generate a sequence of stochastic equations for 100 different seed using the following expression:
set.seed(123)
N <- 100
T <- 1
x <- 10
theta <- c (0 , 5 , 3.5)
Dt <- 1 /N
Y <- numeric (N +1)
Y [1] <- x
Z <- rnorm (N)
for (i in 1: N)
{Y[ i +1] <- Y[ i] + ( theta [1] - theta [2] * Y[ i ]) * Dt + theta [3] * sqrt ( Dt ) *Z [i ]
Y <- ts (Y , start =0 , deltat =1 /N )
Finally, I want to save the 100 "Y" time series into a matrix.
How can I create a loop that save every value for "Y" time series?
If you use replicate as a wrapper around that code as I suggested you will need to put in an additional reference to the Y variable outside the for-loop. Replicate naturally returns a matrix. Using 10 rather than 100 for testing:
set.seed(123)
N=10
> rep.mtx <- replicate( 10, {
+ T <- 1
+ x <- 10
+ theta <- c (0 , 5 , 3.5)
+ Dt <- 1 /N
+ Y <- numeric (N +1)
+ Y [1] <- x
+ Z <- rnorm (N)
+ for (i in 1: N)
+ {Y[ i +1] <- Y[ i] + ( theta [1] - theta [2] * Y[ i ]) * Dt + theta [3] * sqrt ( Dt ) *Z [i ]
+ Y <- ts(Y , start =0 , deltat =1 /N ) } ; Y} )
> rep.mtx
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 10.0000000 10.000000000 10.00000000 10.000000000 10.00000000 10.0000000 10.0000000 10.00000000 10.0000000 10.0000000
[2,] 4.3796671 6.354810283 3.81813573 5.472009398 4.23110027 5.2803722 5.4201839 4.45652809 5.0063798 6.0996073
[3,] 1.9350738 3.575646071 1.66781385 2.409420413 1.88542788 2.6085906 2.1541218 -0.32751756 2.9296172 3.6567678
[4,] 2.6927109 2.231395747 -0.30167191 2.195432765 -0.45782317 1.2568464 0.7082679 0.94938979 1.0545631 2.0926115
[5,] 1.4243939 1.238201192 -0.95757071 2.069632051 2.17168276 2.1431884 -0.7732224 -0.31024651 1.2404757 0.3513411
[6,] 0.8552923 0.003897195 -1.17057706 1.944139651 2.42281031 0.8217115 -1.5728667 -0.91660925 0.3762039 1.6816368
[7,] 2.3258752 1.979699020 -2.45211593 1.734254917 -0.03164826 2.0892811 -0.4504887 0.67679487 0.5553173 0.1764528
[8,] 1.6730784 1.540869016 -0.29879763 1.480201956 -0.46173593 -0.6695147 0.2708330 0.02321148 1.4916370 2.5091604
[9,] -0.5636270 -1.406211817 0.02035412 0.671577271 -0.74736079 0.3122915 0.1940814 -1.33948118 1.2274761 2.9508693
[10,] -1.0420203 0.073152826 -1.24950969 -0.002849978 0.48958280 0.2932273 1.1178037 -0.46907441 0.2529979 1.2145622
[11,] -1.0142676 -0.486707784 0.76296397 -0.422529220 0.15251875 0.3856172 2.8279298 -0.38826177 1.3979960 -0.5287587
Anyone has a tip how to speed up the code below? Particularly with avoiding the for-loops?
J <- 10000
I <- 10000
Y <- matrix(0,J,I)
X <- runif(I,0,1)
P <- runif(I,0,1)
Z <- matrix(runif(n = J*I,0,1),J,I)
K <- matrix(runif(n = J*I,0,1),J,I)
for(j in 1:J){
for (i in 1:I){
Y[j,i] <- X[i]^(Z[j,i])*P[i]^(K[j,i])
}
}
Thanks!
I think t(X^t(Z)*P^t(K)) would lead to the same result and much faster. Here is a reproducible example with a 5 X 5 matrix and performance evaluation.
set.seed(543)
### Original Code
J <- 5
I <- 5
Y <- matrix(0,J,I)
X <- runif(I,0,1)
P <- runif(I,0,1)
Z <- matrix(runif(n = J*I,0,1),J,I)
K <- matrix(runif(n = J*I,0,1),J,I)
for(j in 1:J){
for (i in 1:I){
Y[j,i] <- X[i]^(Z[j,i])*P[i]^(K[j,i])
}
}
# View the result
Y
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.8244760 0.7717289 0.3884273 0.30937614 0.6807137
# [2,] 0.8878758 0.3761184 0.2819624 0.08388850 0.5299624
# [3,] 0.9559749 0.7813653 0.2048310 0.05117558 0.4069641
# [4,] 0.9317235 0.6614524 0.1619824 0.08777542 0.3037913
# [5,] 0.9507279 0.5434549 0.3950076 0.08050582 0.3244810
### A solution without for loop
Y2 <- t(X^t(Z)*P^t(K))
# View the result
Y2
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.8244760 0.7717289 0.3884273 0.30937614 0.6807137
# [2,] 0.8878758 0.3761184 0.2819624 0.08388850 0.5299624
# [3,] 0.9559749 0.7813653 0.2048310 0.05117558 0.4069641
# [4,] 0.9317235 0.6614524 0.1619824 0.08777542 0.3037913
# [5,] 0.9507279 0.5434549 0.3950076 0.08050582 0.3244810
identical(Y, Y2)
# [1] TRUE
### Performance evaluation
library(microbenchmark)
perf <- microbenchmark(
m1 = { Y <- matrix(0,J,I)
for(j in 1:J){
for (i in 1:I){
Y[j,i] <- X[i]^(Z[j,i])*P[i]^(K[j,i])
}
}},
m2 = {Y2 <- t(X^t(Z)*P^t(K))},
times = 100L
)
# View the result
perf
# Unit: microseconds
# expr min lq mean median uq max neval cld
# m1 3649.287 3858.250 4107.31032 3932.017 4112.965 6240.644 100 b
# m2 13.365 14.907 21.66753 15.422 26.731 60.658 100 a
I want to collapse rows in a matrix so that no value of a particular column ever falls below 20. And I want to apply a custom function to the rows to collapse/sum them...
Here is an example matrix:
d <- matrix(data = c(0,105,1,21,2,11,4,5,5,15,7,21,9,1),
ncol = 2,
byrow = TRUE
)
colnames(d) <- c('val','freq')
Looking like this:
d
val freq
[1,] 0 105
[2,] 1 21
[3,] 2 11
[4,] 4 5
[5,] 5 15
[6,] 7 21
[7,] 9 1
The column where the cells must be 20 or above is "freq". So row 1 and 2 are fine, but I need to collapse row 3:5. And I want to replace row 3:5 with the single row from this function:
library(reshape)
replacement <- function(x){
mat <- d[x, ]
mat.res <- untable(mat[ ,c(1, 2)],
num = mat[ ,2]
)
res <- c(mean(mat.res[ ,1]), length(mat.res[ ,1]))
return(res)
}
The function call:
replacement(3:5)
[1] 3.774194 31.000000
Going through the matrix; row 6 is fine, but since row 7 would be left with freq=1 this row needs to be collapsed with row 6. The function call again:
replacement(6:7)
[1] 7.090909 22.000000
The resulting matrix should be:
val freq
[1,] 0 105
[2,] 1 21
[3,] 3.774194 31.000000
[4,] 7.090909 22.000000
The final row numbering is not important.
I have a feeling that the window functions of dplyr might hold the solution, but I need help understanding exactly how. It does not have to be dplyr. I take whatever works ;-)
For future reference, this is not very elegant, but it works...
rows <- dim(d)[1]
tmp <- NULL
inc <- 1
tmpSum <- 0
for(i in 1:rows){
if(d[i, 2] > 19){
tmp <- rbind(tmp, c(d[i, ], inc))
inc <- inc + 1
tmpSum <- 0
} else {
tmp <- rbind(tmp, c(d[i, ], inc))
tmpSum <- d[i,2] + tmpSum
if(tmpSum > 19){
inc <- inc + 1
}
}
}
if(sum(tmp[tmp[ ,3] == max(tmp[ ,3]), 2]) < 19){
tmp[tmp[ ,3] == max(tmp[ ,3]), 3] <- tmp[tmp[ ,3] == max(tmp[ ,3]), 3]-1
}
res <- NULL
for(i in 1:max(tmp[ ,3])){
val <- mean(rep(tmp[tmp[ ,3] == i, 1], tmp[tmp[ ,3] == i, 2]))
freq <- length(rep(tmp[tmp[ ,3] == i, 1], tmp[tmp[ ,3] == i, 2]))
res <- rbind(res, c(val, freq))
}
res