Ritu
Ritu

Reputation: 15

Convert a R matrix with lists into another R matrix with nested lists

I don't have much experience with R and want some help in modifying matrix or dataframes. I have a csv file which looks like following:

m1 m2 m3 m4 m5
c1 1 0 NA 1 0
c2 0 0 1 1 NA
c3 1 1 1 1 1
c4 0 1 0 NA 1

I read the csv file into a matrix using the following code:

data <- read.csv(‘file.csv’, sep=“\t”, stringsAsFactors = F,head = T, row.names = 1)`enter code here`
data <- as.matrix(data)
str(data)

After doing str(data) I get the following output:

int [1:4, 1:5] 1 0 1 NA 1 0 ...
 - attr(*, “dimnames”)=List of 2
     ..$ : chr [1:4] “c1” “c2" “c3” “c4" ...
     ..$ : chr [1:5] “m1” “m2" “m3” “m4" ...

What I want after reading the csv is to get a matrix or dataframe (whichever can be saved to Rdata easily) with each rows as a separate list and the column values for each row as a list within the row list. Specifically, I want something like the following:

List of 4
$ 1st list: int[1, 1:5] 1 0 NA ...
    ..-attr(*, "dimnames")=List of 2
      .. ..$ : chr [1] “c1”
      .. ..$ : chr [1:5] “m1” “m2" “m3” “m4" ...

$ 2nd list: int[1, 1:5] 1 0 NA ...
    ..-attr(*, "dimnames")=List of 2
      .. ..$ : chr [1] “c1”
      .. ..$ : chr [1:5] “m1” “m2" “m3” “m4" ...

$ 3rd list: int[1, 1:5] 1 0 NA ...
    ..-attr(*, "dimnames")=List of 2
      .. ..$ : chr [1] “c1”
      .. ..$ : chr [1:5] “m1” “m2" “m3” “m4" ...

$ 4th list: int[1, 1:5] 1 0 NA ...
    ..-attr(*, "dimnames")=List of 2
      .. ..$ : chr [1] “c1”
      .. ..$ : chr [1:5] “m1” “m2" “m3” “m4" ...

I understand there can be various ways to get this. It can be either while reading the csv or after converting it into a matrix and create nested lists based on row indices. It would be really helpful if I can get it with the second approach based on row indices. I want to save the output Lists of 4 into a RData from the final matrix or dataframe.

EDIT: Includes solution

I was able to split the dataframe into each single row like @user20650 suggested using the following code:

data_new <- split.data.frame(data, row.names(data))

This created 4 lists like I wanted. I also found out that if we want to split the dataframe into desired number of rows we can do so using column indices. Finally, we can merge the splitted dataframes into a single dataframe as lists and get similar output. Here is the code for that:

data_frame_1 <- data[1:2,]
data_frame_2 <- data[3:4,]
df_list <- list("T1" = data_frame_1,"T2" = data_frame_2)

The final dataframe df_list str(df_list) will look like the following :

List of 2
 $ T1: int [1:2, 1:5] 1 0 NA 1 0 1 0 ...
    ..- attr(*, "dimnames")=List of 2
      .. ..$ : chr [1:2] "c1" "c2"
      .. ..$ : chr [1:6] "m1" "m2" "m3" "m4" ...

 $ T2: int [1:2, 1:5] 1 0 1 NA 0 1 0 1 NA 1 ...
    ..- attr(*, "dimnames")=List of 2
      .. ..$ : chr [1:2] "c3" "c4"
      .. ..$ : chr [1:6] "m1" "m2" "m3" "m4" ...

Upvotes: 0

Views: 145

Answers (2)

jay.sf
jay.sf

Reputation: 73342

You may want to use drop=FALSE to prevent single rows automatically coerced into vectors.

res <- lapply(seq_len(nrow(dat)), \(i) dat[i,, drop=FALSE])

str(res)
# List of 4
# $ : int [1, 1:5] 1 0 NA 1 0
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : chr "c1"
# .. ..$ : chr [1:5] "m1" "m2" "m3" "m4" ...
# $ : int [1, 1:5] 0 0 1 1 NA
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : chr "c2"
# .. ..$ : chr [1:5] "m1" "m2" "m3" "m4" ...
# $ : int [1, 1:5] 1 1 1 1 1
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : chr "c3"
# .. ..$ : chr [1:5] "m1" "m2" "m3" "m4" ...
# $ : int [1, 1:5] 0 1 0 NA 1
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : chr "c4"
# .. ..$ : chr [1:5] "m1" "m2" "m3" "m4" ...

Data:

dat <- structure(c(1L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, NA, 1L, 1L, 0L, 1L, 
1L, 1L, NA, 0L, NA, 1L, 1L), dim = 4:5, dimnames = list(c("c1", 
"c2", "c3", "c4"), c("m1", "m2", "m3", "m4", "m5")))

Upvotes: 1

Talha Asif
Talha Asif

Reputation: 401

Here's the code to create a list of lists from the dataframe:

data <- read.table(text = "m1   m2  m3  m4  m5
c1  1   0   NA  1   0
c2  0   0   1   1   NA
c3  1   1   1   1   1
c4  0   1   0   NA  1", header = TRUE, sep = "\t", stringsAsFactors = FALSE)


lst <- lapply(1:nrow(data), function(i) {
  as.list(data[i, ])
})
names(lst) <- data[, 1]
lst

Upvotes: 0

Related Questions