I have four matrices which contain positive and negative values. Now I would like to convert all negative values for each matrix to NA. The matrices are called Main_mean, Inn_mean, Isar_mean and Danube_mean.
For a single matrix this would be quite easy:
Main_mean[Main_mean<=0] <- NA.
But how should it look like in a loop?
Get the matrix in a list and apply the function to each one using lapply :
list_obj <- mget(ls(pattern = '_mean$'))
#Or make a list individually
#list_obj <- mget(c('Main_mean', 'Danube_mean', 'Inn_mean', 'Isar_mean'))
result <- lapply(list_obj, function(x) {x[x<=0] <- NA;x})
To replace the original objects you can use list2env.
list2env(result, .GlobalEnv)
Related
For following argument
x <- c(1,3,4,24,1,2,2,2,1,3,3,1,1,0,8)
A <- matrix(x,nrow = 5)
n <- ncol(A)
t(A)
meancol <- colMeans(A)
meancol
t(t(meancol))
I am writing to ask why for t(A), I only need put t() to get what I want, but for meancol,I need to put t(t()) to get the results.
Notice that the output of meancol <- colMeans(A) isn't a matrix, then the function transpose interprets it as a vector.
From the Details of the function t() we have:
Details This is a generic function for which methods can be written.
The description here applies to the default and "data.frame" methods.
A data frame is first coerced to a matrix: see as.matrix. When x is a
vector, it is treated as a column, i.e., the result is a 1-row matrix.
The vector is read as a 1-column matrix, therefore the result is a 1-row matrix.
I am creating 15 rows in a dataframe, like this. I cannot show my real code, but the create row function involves complex calculations that can be put in a function. Any ideas on how I can do this using lapply, apply, etc. to create all 15 in parallel and then concatenate all the rows into a dataframe? I think using lapply will work (i.e. put all rows in a list, then unlist and concatenate, but not exactly sure how to do it).
for( i in 1:15 ) {
row <- create_row()
# row is essentially a dataframe with 1 row
rbind(my_df,row)
}
Something like this should work for you,
create_row <- function(){
rnorm(10, 0,1)
}
my_list <- vector(100, mode = "list")
my_list_2 <- lapply(my_list, function(x) create_row())
data.frame(t(sapply(my_list_2,c)))
The create_row function is just make the example reproducible, then we predefine an empty list, then fill it with the result from the create_row() function, then convert the resulting list to a data frame.
Alternatively, predefine a matrix and use the apply functions, over the row margin, then use the t (transpose) function, to get the output correct,
df <- data.frame(matrix(ncol = 10, nrow = 100))
t(apply(df, 1, function(x) create_row(x)))
I have a function f(list,t) where the first argument is a list and the second one t is a number. I wanna apply f to columns of a matrix M and elements of a vector T respectively. Hence, if columns of M are (M_1,M_2,...,M_k) and T = (t_1,t_2,...,t_k), I want to get the following :
f(M_1,t_1), f(M_2,t_2), ..., f(M_k,t_k).
Is there an efficient way doing so without using for loop?
For example if
f <- function(list,x) {x %in% list}
M <- matrix(1:12,4,3)
T <- c(1,2,10)
I expect to get
TRUE FALSE TRUE
The following line applies f on each column of M and each element of T
apply(M,2,f,T)
But what I need is just the diagonal of this output, so I want a way to avoid extra computations.
You can also use sapply using the number of columns in the matrix. Later, we use any to return True (if any) value from each column
Tr <- c(1,2,10)
sapply(seq(ncol(M)), function(x) any(f(M[,x], Tr)))
[1] TRUE FALSE TRUE
Convert your matrix to a data frame and then use the map2 function from the purrr package:
library(tidyr)
df <- as.data.frame(M)
unlist(map2(df, t, f))
Also it is a terrible idea to name a variable T (or F) as that can cause a ton of problems with logical terms.
mapply(f,as.data.frame(M),T)
as.data.frame is needed to convert M to the list of the matrix columns, and mapply applies f to the produced list and vector T in a pairwise fashion.
df is a frequency table, where the values in a were reported as many times as recorded in column x,y,z. I'm trying to convert the frequency table to the original data, so I use the rep() function.
How do I loop the rep() function to give me the original data for x, y, z without having to repeat the function several times like I did below?
Also, can I input the result into a data frame, bearing in mind that the output will have different column lengths:
a <- (1:10)
x <- (6:15)
y <- (11:20)
z <- (16:25)
df <- data.frame(a,x,y,z)
df
rep(df[,1], df[,2])
rep(df[,1], df[,3])
rep(df[,1], df[,4])
If you don't want to repeat the for loop, you can always try using an apply function. Note that you cannot store it in a data.frame because the objects are of different lengths, but you could store it in a list and access the elements in a similar way to a data.frame. Something like this works:
df2<-sapply(df[,2:4],function(x) rep(df[,1],x))
What this sapply function is saying is for each column in df[,2:4], apply the rep(df[,1],x) function to it where x is one of your columns ( df[,2], df[,3], or df[,4]).
The below code just makes sure the apply function is giving the same result as your original way.
identical(df2$x,rep(df[,1], df[,2]))
[1] TRUE
identical(df2$y,rep(df[,1], df[,3]))
[1] TRUE
identical(df2$z,rep(df[,1], df[,4]))
[1] TRUE
EDIT:
If you want it as a data.frame object you can do this:
res<-as.data.frame(sapply(df2, '[', seq(max(sapply(df2, length)))))
Note this introduces NAs into your data.frame so be careful!
Starting with an empty dataframe, I need to fill the dataframe as follows: A for loop generates a fixed number of values in each iteration, and I need to add a new column with the values in that list, and giving the column a unique name, col_i (where i is the ith iteration of the loop).
How can this (seemingly simple task) be done?
The most efficient way to build a dataframe piecewise is to store your parts in a pre-allocated list, then put them together afterwards.
For example:
num.iters <- 10
l <- vector('list', num.iters)
for (i in 1:num.iters) {
l[[i]] <- rnorm(3) # the column data
names(l)[i] <- paste('Col', i, sep='.') # the column name
}
do.call(cbind, l) # ... if your cols are the same datatype and you want a matrix
data.frame(l) # otherwise
What's wrong with ?cbind?
The functions cbind and rbind are S3 generic, with methods for data frames.
The data frame method will be used if at least one argument is a data frame
and the rest are vectors or matrices.
?colnames can also be applied to data.frames