I have two matrices in a list:
colList <- list()
colList[["V1"]] <- as.matrix(c("asd", "asd", "asd"))
colList[["V2"]] <- as.matrix(c("das", "das", "das"))
And I want to cbind the values of a data.frame value.frame$keyID to each sublist. The first value (2000) to the first sublist, the second value (3000) to the second sublist.
Here the value.frame:
value.frame <- data.frame(keyID =c("2000", "3000"))
The result should look like this:
colList <- list()
colList[["V1"]] <- matrix(c("asd", "asd", "asd", 2000, 2000, 2000),
nrow=3,
ncol=2)
colList[["V2"]] <- matrix(c("das", "das", "das", 3000, 3000, 3000),
nrow=3,
ncol=2)
I tried it with the following code, but the result is not the desired one. Hope someone can help me.
mapply( cbind, colList, paste(value.frame[,1]))
Using lapply and seq_along
nms <- names(colList)
colList <- lapply(seq_along(colList), x=colList,
y=as.character(value.frame$keyID), function(j, x, y) {
cbind(x[[j]], y[j])
})
names(colList) <- nms
colList[["V1"]]
[,1] [,2]
[1,] "asd" "2000"
[2,] "asd" "2000"
[3,] "asd" "2000"
colList[["V2"]]
[,1] [,2]
[1,] "das" "3000"
[2,] "das" "3000"
[3,] "das" "3000"
You could do this with mapply using the option SIMPLIFY=FALSE
mapply(cbind, colList, as.character(value.frame$keyID), SIMPLIFY=FALSE)
#$V1
# [,1] [,2]
#[1,] "asd" "2000"
#[2,] "asd" "2000"
#[3,] "asd" "2000"
#$V2
# [,1] [,2]
#[1,] "das" "3000"
#[2,] "das" "3000"
#[3,] "das" "3000"
Or using Map which is a wrapper for mapply(..., SIMPLIFY=FALSE)
Map(cbind, colList, as.character(value.frame$keyID))
Related
I´m trying to get different elements from multiple diagonal saved as lists. My data looks something like this:
res <- list()
res[[1]] <- matrix(c(0.04770856,0.02854005,0.02854005,0.03260190), nrow=2, ncol=2)
res[[2]] <- matrix(c(0.05436957,0.04887182,0.04887182, 0.10484454), nrow=2, ncol=2)
> res
[[1]]
[,1] [,2]
[1,] 0.04770856 0.02854005
[2,] 0.02854005 0.03260190
[[2]]
[,1] [,2]
[1,] 0.05436957 0.04887182
[2,] 0.04887182 0.10484454
> diag(res[[1]])
[1] 0.04770856 0.03260190
> diag(res[[2]])
[1] 0.05436957 0.10484454
I would like to save the first and second elements of each diagonal of a given list into a vector similar to this:
d.1st.el <- c(0.04770856, 0.05436957)
d.2nd.el <- c(0.03260190, 0.10484454)
My issue is to write the function that runs for all given lists and get the diagonals. For some reason, when I use unlist() to extract the values of each matrix for a given level, it doesn't get me the number but the full matrix.
Does anyone have a simple solution?
sapply(res, diag)
[,1] [,2]
[1,] 0.04770856 0.05436957
[2,] 0.03260190 0.10484454
# or
lapply(res, diag)
[[1]]
[1] 0.04770856 0.03260190
[[2]]
[1] 0.05436957 0.10484454
If you want the vectors for some reason in your global environment:
alld <- lapply(res, diag)
names(alld) <- sprintf("d.%d.el", 1:length(alld))
list2env(alld, globalenv())
In two steps you can do:
# Step 1 - Get the diagonals
all_diags <- sapply(res, function(x) diag(t(x)))
print(all_diags)
[,1] [,2]
[1,] 0.04770856 0.05436957
[2,] 0.03260190 0.10484454
# Step 2 - Append to vectors
d.1st.el <- all_diags[1,]
d.2nd.el <- all_diags[2,]
I am having 3 matrices that store values from triplicate measurements and would like to take the mean of the 3 matrices.
So let's say the three matrices are:
m1<-t(matrix(c("text", 1:3), ncol=2, nrow=4))
m2<-t(matrix(c("text", 1:3), ncol=2, nrow=4))
m3<-t(matrix(c("text", 1:3), ncol=2, nrow=4))
> m1
[,1] [,2] [,3] [,4]
[1,] "text" "1" "2" "3"
[2,] "text" "1" "2" "3"
> m2
[,1] [,2] [,3] [,4]
[1,] "text" "1" "2" "3"
[2,] "text" "1" "2" "3"
> m3
[,1] [,2] [,3] [,4]
[1,] "text" "1" "2" "3"
[2,] "text" "1" "2" "3"
I would like to have this for every position of the matrices:
mean(m1[i,j], m2[i,j], m2[i,j])
So I tried it with 2 for loops:
for(i in ncol(m1)){
for(j in nrow(m1)){
means[i,j]<-mean(m1[i,j], m2[i,j], m2[i,j])
}
which obviously doesn't work
The text in the first column isn't an issue if NA is returned.
Anyone could help me please?
Thanks!
We can place it in a list, convert to numeric and use Reduce
lst <- lapply(list(m1[, -1], m2[,-1], m3[, -1]), as.numeric)
Reduce(`+`,lst)/length(lst)
If there are many matrices starting with 'm', we can use mget
lst <- lapply(mget(paste0("m", 1:3)), function(x) as.numeric(x[,-1]))
and then do the Reduce step.
I have a matrix that contains integer values that represent the index of the item in an array and I'd like to switch out item 1 for the values[1] and so on for each item in the values array.
Some code to demonstrate what I'd like
> m = matrix(1:3, ncol=3, nrow=3)
> m
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
> replace(m, 1="a", 2="b", 3="c")
> m
[,1] [,2] [,3]
[1,] "a" "a" "a"
[2,] "b" "b" "b"
[3,] "c" "c" "c"
Basically it takes 1 and turns it into "a" and so on. It seems like if I try to do this with a for loop it changes after the first iteration from int to string and since I'd like to do this with any object type that's not great behavior.
I can think of three possibilities to solve this
m <- matrix(1:3, 3, 3) # Your data
1
Either define a function that will get a vector in the correct matching order (the first entry will match the first unique value in m, etc.)
vec <- c("Ralf", "Jhons", "Pete")
Then you can define a simple function such as
Match_func <- function(x, y) "dim<-"(y[match(unique(x), seq_along(y))], dim(x))
Test
Match_func(m, vec)
# [,1] [,2] [,3]
# [1,] "Ralf" "Ralf" "Ralf"
# [2,] "Jhons" "Jhons" "Jhons"
# [3,] "Pete" "Pete" "Pete"
2
The second option will be to define your manual replace function, something like
Match_func2 <- function(x, ...) {
temp <- list(...)[[1]]
"dim<-"(temp[match(x, as.numeric(names(temp)))], dim(x))
}
Test
Match_func2(m, c("1" = "a", "2" = "b", "3" = "c"))
# [,1] [,2] [,3]
# [1,] "a" "a" "a"
# [2,] "b" "b" "b"
# [3,] "c" "c" "c"
3
You can also make a use of plyr::revalue
library(plyr)
Match_func3 <- function(x, ...) {
temp <- list(...)[[1]]
"dim<-"(revalue(as.character(x), temp), dim(x))
}
Test
Match_func3(m, c("1" = "a", "2" = "b", "3" = "c"))
# [,1] [,2] [,3]
# [1,] "a" "a" "a"
# [2,] "b" "b" "b"
# [3,] "c" "c" "c"
Note: The last approach is the safest in case you don't want to replace all the unique values
Here's an option, starting with a character matrix so that you don't need to worry about making a copy or coercion of the original matrix.
m = matrix(as.character(1:3), ncol=3, nrow=3)
old <- as.character(1:3)
new <- c("a", "b", "c")
for (i in 1:length(old)) {
m <- ifelse(m == old[i], new[i], m)
}
I have a matrix "a" like the following:
a<-rbind(c("a1","ost1;ost2;ost3","utr;body;pro"),
c("a2","idh1;idh2","pro;body"),
c("a3","dnm1","body"))
>a
[,1] [,2] [,3]
[1,] "a1" "ost1;ost2;ost3" "utr;body;pro"
[2,] "a2" "idh1;idh2" "pro;body"
[3,] "a3" "dnm1" "body"
I want to get a matrix "b" like this
[,1] [,2] [,3]
[1,] "a1" "ost1" "utr"
[2,] "a1" "ost2" "body"
[3,] "a1" "ost3" "pro"
[4,] "a2" "idh1" "pro"
[5,] "a2" "idh2" "body"
[6,] "a3" "dnm1" "body"
OK, get it:
b<-do.call(rbind, (apply(a, 1, function(x) {do.call(cbind, strsplit(x,";"))})))
Your solution, without the unnecessary parentheses:
do.call(rbind, apply(a, 1, function(x) do.call(cbind, strsplit(x, ";"))))
This also works:
do.call(rbind, lapply(apply(a, 1, strsplit, ';'), do.call, what = cbind))
Not that there is anything wrong with using anonymous functions (function(x){...}), but some people find it more "elegant" without any.
If I have a data.frame(sum_clus) with 600 columns(variables) and 10 rows which have no NA's and are all numeric values, how can I create 5 new variables that give me the column names of the top 5 variables in that row?
For eg.
max <- apply(sum_clus ,1, max)
for(ii in 1:10) sum_clus$max[ii] <- colnames(sum_clus)[which(sum_clus[ii , ]
== sum_clus[ii, sum_clus[ii,] == max[ii]])]
This above code helped me create a variable sum_clus$max which gives me the column name of the max variable in each row. Similarly, how can I get 5 such variables that give me the column names of the top 5 variables? sum_clus$max, sum_clus$second_but_max, and so on..
Thanks in advance!
One option is to use order() and then use that to subset the column names, e.g.:
set.seed(1)
df <- data.frame(matrix(runif(600*10), ncol = 600))
foo <- function(x, names) {
ord <- order(x, decreasing = TRUE)[1:5]
names[ord]
}
nams <- colnames(df)
apply(df, 1, foo, names = nams)
Producing
> apply(df, 1, foo, names = nams)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "X369" "X321" "X348" "X415" "X169" "X258" "X55" "X182" "X99" "X78"
[2,] "X42" "X295" "X563" "X173" "X377" "X31" "X246" "X353" "X259" "X384"
[3,] "X98" "X440" "X371" "X207" "X429" "X292" "X433" "X437" "X123" "X558"
[4,] "X13" "X193" "X396" "X78" "X543" "X228" "X211" "X2" "X583" "X508"
[5,] "X35" "X364" "X249" "X33" "X388" "X405" "X458" "X252" "X569" "X456"
Check this works:
> names(sort(unlist(df[1,, drop = TRUE]), decreasing = TRUE)[1:5])
[1] "X369" "X42" "X98" "X13" "X35"
> names(sort(unlist(df[2,, drop = TRUE]), decreasing = TRUE)[1:5])
[1] "X321" "X295" "X440" "X193" "X364"
Seems OK.
Here's a similar solution, using (i) a loop instead of apply; and (ii) rank instead of order.
set.seed(1)
n_i = 10
n_ii = 600
n_top = 5
df <- data.frame(matrix(runif(n_ii*n_i), ncol = n_ii))
out <- matrix("",n_top,n_i)
for (i in 1:n_i){
colranks <- rank(df[i,])
out[,i] <- names(sort(colranks)[n_ii:(n_ii-(n_top-1))])
}
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] "X369" "X321" "X348" "X415" "X169" "X258" "X55" "X182" "X99" "X78"
# [2,] "X42" "X295" "X563" "X173" "X377" "X31" "X246" "X353" "X259" "X384"
# [3,] "X98" "X440" "X371" "X207" "X429" "X292" "X433" "X437" "X123" "X558"
# [4,] "X13" "X193" "X396" "X78" "X543" "X228" "X211" "X2" "X583" "X508"
# [5,] "X35" "X364" "X249" "X33" "X388" "X405" "X458" "X252" "X569" "X456"
The one-liner analogue with apply is
apply(df,1,function(x)names(sort(rank(x))))[600:596,]