So I have a matrix TMatrix that i'm cycling through, and I want to put the row and column names for every cell that contains a value that is not finite into a table. I've tried to doing the following, but I keep getting NA for the row and column names. What's going on?
AA <- 1:rowlength
BB <- 1:ncol(Nmatrix)
for(i in AA){
for(j in BB){
if (is.finite(TMatrix[i,j])==FALSE){
TNS <- matrix(data=NA,nrow=1,ncol=4)
TNS[1,1] <- TMatrix[i,j]
TNS[1,2] <- Nmatrix[i,j]
TNS[1,3] <- paste(rownames(TMatrix)[TMatrix[i,j]])
TNS[1,4] <- paste(colnames(TMatrix)[TMatrix[i,j]])
TMinf <- rbind(TMinf,TNS)
}
PMatrix[i,j] <- pt(TMatrix[i,j],n1+n2-2)
}
}
No idea what this is doing because you provided zero of the objects we would need to run this, but it sounds like you are wanting to do something in the following example:
mat <- matrix(rnorm(20), nrow = 4)
mat[1, 4] <- mat[3, 2] <- NA
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0.11025848 1.1021023 -0.3098129 NA -0.1358902
# [2,] 0.00351275 0.1440906 1.2141437 0.2601651 0.2504035
# [3,] -1.11565805 NA 0.1483867 -0.4102958 -0.3104319
# [4,] 0.34785864 1.5319365 1.2750632 0.1259548 -0.7594117
which(!is.finite(mat), arr.ind = TRUE)
# row col
# [1,] 3 2
# [2,] 1 4
If you have the rows/columns named:
colnames(mat) <- LETTERS[1:5]
rownames(mat) <- letters[1:4]
# A B C D E
# a 0.11025848 1.1021023 -0.3098129 NA -0.1358902
# b 0.00351275 0.1440906 1.2141437 0.2601651 0.2504035
# c -1.11565805 NA 0.1483867 -0.4102958 -0.3104319
# d 0.34785864 1.5319365 1.2750632 0.1259548 -0.7594117
idx <- which(!is.finite(mat), arr.ind = TRUE)
rownames(mat)[idx[ , 'row']]
# [1] "c" "a"
colnames(mat)[idx[ , 'col']]
# [1] "B" "D"
Never mind, I figured it out. I had the index wrong. It should be like this:
AA <- 1:rowlength
BB <- 1:ncol(Nmatrix)
for(i in AA){
for(j in BB){
if (is.finite(TMatrix[i,j])==FALSE){
TNS <- matrix(data=NA,nrow=1,ncol=4)
TNS[1,1] <- TMatrix[i,j]
TNS[1,2] <- Nmatrix[i,j]
TNS[1,3] <- rownames(TMatrix)[i]
TNS[1,4] <- colnames(TMatrix)[j]
TMinf <- rbind(TMinf,TNS)
}
PMatrix[i,j] <- pt(TMatrix[i,j],n1+n2-2)
}
}
Related
I have a positive definite symmetric matrix. Pasting the matrix generated using the following code:
set.seed(123)
m <- genPositiveDefMat(
dim = 3,
covMethod = "unifcorrmat",
rangeVar = c(0,1) )
x <- as.matrix(m$Sigma)
diag(x) <- 1
x
#Output
[,1] [,2] [,3]
[1,] 1.0000000 -0.2432303 -0.4110525
[2,] -0.2432303 1.0000000 -0.1046602
[3,] -0.4110525 -0.1046602 1.0000000
Now, I want to run the matrix through iterations and in each iteration I want to replace the symmetric pair with NA. For example,
Iteration 1:
x[1,2] = x[2,1] <- NA
Iteration2:
x[1,3] = x[3,1] <- NA
and so on....
My idea was to check using a for loop
Prototype:
for( r in 1:nrow(x)
for( c in 1:ncol(x)
if x[r,c]=x[c,r]<-NA
else
x[r,c]
The issue with my code is for row 1 and column 1, the values are equal hence it sets to 0 (which is wrong). Also, the moment it is not NA it comes out of the loop.
Appreciate any help here.
Thanks
If you need the replacement done iteratively, you can use the indexes of values represented by upper.tri(x)/lower.tri to do the replacements pair-by-pair. That will allow you to pass the results to a function before/after each replacement, e.g.:
idx <- which(lower.tri(mat), arr.ind=TRUE)
sel <- cbind(
replace(mat, , seq_along(mat))[ idx ],
replace(mat, , seq_along(mat))[ idx[,2:1] ]
)
# [,1] [,2]
#[1,] 2 4 ##each row represents the lower/upper pair
#[2,] 3 7
#[3,] 6 8
for( i in seq_len(nrow(sel)) ) {
mat[ sel[i,] ] <- NA
print(mean(mat, na.rm=TRUE))
}
#[1] 0.2812249
#[1] 0.5581359
#[1] 1
I have two matrices, one of them has a NA value and I want to use a function that only runs if there are NAs present in the data, so if I run the function it should only work on df2 and not df1. How would I do this?
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(1,2,3,NA, nrow = 2, ncol = 2)
Based on the comment above, here is a complete answer (assuming I understand what you are getting at). The function is set up to do something or not to the matrix depending on whether it has NA values.
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(c(1,2,3,NA), nrow = 2, ncol = 2)
myfunc <- function(m) {
ret <- m
if (all(!is.na(m))) {
print("This matrix has no NAs")
} else {
print("This matrix has NAs")
}
return(ret)
}
myfunc(df1)
# [1] "This matrix has no NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
myfunc(df2)
# [1] "This matrix has NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 NA
I want to run a for loop over a list. I have 3 questions:
I wonder how I select each list in "i in 1:list", when doing the same for a data frame it can be for(i in 1:ncol(df)), but how should this be written for a list?
I also wonder how I could "add on" the values for each loop to the " output" matrix?
How to convert a list to a data frame. When doing it like data.frame(df3) they will be added column wise, number of rows will always be 3.
Many thanks if someone has suggestions!
name <- rep("gg",3)
id <- LETTERS[1:3]
emmeans <- runif(1:3)
SE <- runif(1:3)
p <- rep(c(0.001),3)
df <- data.frame(name,id, emmeans,p)
df
df <- list(df)
name <- rep("ff",3)
id <- LETTERS[1:3]
emmeans <- runif(1:3)
SE <- runif(1:3)
p <- rep(c(0.003),3)
df2 <- data.frame(name,id, emmeans,p)
df2 <- list(df2)
df3 <- list(df,df2)
df3
> df3
[[1]]
[[1]][[1]]
name id emmeans p
1 gg A 0.2248491 0.001
2 gg B 0.4213938 0.001
3 gg C 0.3671521 0.001
[[2]]
[[2]][[1]]
name id emmeans p
1 ff A 0.2561801 0.003
2 ff B 0.1705811 0.003
3 ff C 0.9714178 0.003
output <- matrix(nrow=2, ncol=5)
for(i in 1:list){ # what could be written here?
d <- as.data.frame(df3[[i]])
for(j in 1:nrow(d)){
output[i,1] <- d[1,3]
output[i,2] <- d[2,3]
output[i,3] <- d[3,3]
output[i,4] <- d[1,4]
output[i,5] <- d[1,1]
}
}
#Wanted outcome:
output
[,1] [,2] [,3] [,4] [,5]
[1,] "0.224849119782448" "0.421393777942285" "0.367152112303302" "0.001" "gg"
[2,] "0.256180095253512" "0.170581063022837" "0.971417842432857" "0.003" "ff"
This data is weirdly structured enough, and the extraction is unique enough, that I think a for loop is the easiest way. Something like this:
output <- matrix(nrow = length(df3), ncol=5)
for(i in seq_along(df3)) {
output[i, ] = with(df3[[i]], c(emmeans, p[1], name[1]))
}
output
# [,1] [,2] [,3] [,4] [,5]
# [1,] "0.0101301828399301" "0.21454192395322" "0.913734979229048" "0.003" "ff"
# [2,] "0.0101301828399301" "0.21454192395322" "0.913734979229048" "0.003" "ff"
I am trying to iterate through each row in a matrix, find the column with the minimum value and the column name and then delete that column after it has been used so that a new minimum can be calculated. The correct answer should look like this:
result
1/1 50
2/2 61
3/3 72
4/4 83
Test_Matrix <- matrix(c(50:149), ncol = 10 , byrow=FALSE)
Names <- c(1:10)
colnames(Test_Matrix) <- Names
rownames(Test_Matrix) <- Names
result <- t(sapply(seq(nrow(Test_Matrix)), function(i) {
j <- which.min(Test_Matrix[i,])
c(paste(rownames(Test_Matrix)[i], colnames(Test_Matrix)[j], sep='/'), Test_Matrix[i,j])
drops <- colnames(Test_Matrix)[j]
Test_Matrix[ , !(names(Test_Matrix) %in% drops)]
}))
result
Second question is that I would like to choose the order of the rows during the iteration so that it chooses to go to the next row that had the same name as the column name. For example, if the column with the minimum was named 5, column 5 would be deleted and the minimum for the row named 5 would be calculated next.
Wondering if this is possible and if a loop is needed for these calculations.
As a new R user, I appreciate any help.
Thanks!
For the first part of your question:
Test_Matrix <- matrix(c(50:149), ncol = 10 , byrow=FALSE)
Names <- c(1:10)
colnames(Test_Matrix) <- Names
rownames(Test_Matrix) <- Names
result <- matrix(nrow=0, ncol=2)
for (i in 1:nrow(Test_Matrix)) {
Test_Matrix <- as.matrix(Test_Matrix) #when Test_Matrix has only 1 column R converts it into a vector
j <- which.min(Test_Matrix[i, ])
result <- rbind(result, c(paste(rownames(Test_Matrix)[i],
colnames(Test_Matrix)[j], sep='/'),
as.numeric(Test_Matrix[i,j])))
Test_Matrix <- Test_Matrix[, -j] #remove column j
}
result
## [,1] [,2]
## [1,] "1/1" "50"
## [2,] "2/2" "61"
## [3,] "3/3" "72"
## [4,] "4/4" "83"
## [5,] "5/5" "94"
## [6,] "6/6" "105"
## [7,] "7/7" "116"
## [8,] "8/8" "127"
## [9,] "9/9" "138"
##[10,] "10/" "149"
Edit: For the second part, instead of the for loop, you can use this:
i <- 1
while(length(Test_Matrix)>0) {
Test_Matrix <- as.matrix(Test_Matrix)
j <- which.min(Test_Matrix[i, ])
result <- rbind(result, c(paste(rownames(Test_Matrix)[i],
colnames(Test_Matrix)[j], sep='/'),
as.numeric(Test_Matrix[i,j])))
Test_Matrix <- Test_Matrix[, -j]
i <- as.numeric(names(j))+1
}
When running the following code
test <- function(p){
set.seed(1984)
for(i in 1:p){
x <- matrix()
n <- function(){sample(1:10, size = 1)}
draws <- function(){sample(LETTERS[1:10], n(), replace = T)}
x[i] <- paste(draws(), sep = '-', collapse = '')
}
return(x)
}
R returns the following output:
> test(10)
[1] NA NA NA NA NA NA NA NA NA "GE"
When I am expecting to see this matrix filled with random (number of) letters in each row separated by dashes (-).
Any ideas?
Putting various comments from Jthorpe and me together, you might consider
test <- function(p){
x <- character()
for(i in 1:p){
n <- function(){sample(1:10, size = 1)}
draws <- function(){sample(LETTERS[1:10], n(), replace = T)}
x[i] <- paste(draws(), collapse = '-')
}
return(as.matrix(x))
}
set.seed(1984)
test(10)
which produces a matrix with dashes between letters
[,1]
[1,] "E-D-D-H-I-A-E"
[2,] "C-I-A-H-H-C-A-C-G"
[3,] "C-G-A-G-I-H-B-I-F-F"
[4,] "J-D-F-H-A-E"
[5,] "D-A-C-I-C-G"
[6,] "C-G-I-E"
[7,] "G-F-B-F-B"
[8,] "A-C-A-I-C-B-I-A"
[9,] "H-H-I"
[10,] "G-E"