How to import Matlab table ('cell' structure) to R dataframe while conserving proper structure/order?
I still don't know why MAT v5
needs to import tables to lists, but I unexpectedly found a solution!
The function below will easily extract a specific row from that type of list, where list
is your list, row
is the row you want to extract, and nrow
is the total number of rows (given that you know these details):
matlab.row <- function(list,row,nrow) {
unlist(list[seq(row, length(list), nrow)]) # This will take every nth element starting from desired row
}
matlab.row(mylist,1,4)
"2" "34" "17"
matlab.row(mylist,2,4)
"32" "43"
matlab.row(mylist,3,4)
"C" "D" "A" "F" "G" "I"
matlab.row(mylist,4,4)
"455"
In order to get the full data frame, I had to tweak the function some more, where list
is your list, max.len
is the length of the longest row (max number of items), and nrow
is your total number of rows:
matlab.df <- function(list,max.len,nrow) {
matlab.row <- function(list,row,nrow) { # We reuse the function we just made earlier
unlist(list[seq(row, length(list), nrow)])
}
listA <- vector('list', nrow) # Precreates list
for (i in 1:nrow) {
listA[i] <- list(c(matlab.row(list,i,nrow), # Combines output from last function to NAs on next line
rep(NA, max.len - length(matlab.row(list,i,nrow))))) # Fills the remaining columns with NAs (very important part!)
}
df <- do.call(rbind,listA) # Binds elements together from the list we created as rows
df # Prints dataframe
}
matlab.df(list = mylist, max.len = 6, nrow = 4)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] "2" "34" "17" NA NA NA
[2,] "32" "43" NA NA NA NA
[3,] "C" "D" "A" "F" "G" "I"
[4,] "455" NA NA NA NA NA
I found the solution thanks to a combination of these threads: 1, 2, 3, and 4.
R - Help converting nested lists(?) to data.frame
Why not just extract from that list object?
dat <- as.data.frame( mlab$ DATA[1:15])
colnames(dat) <- unlist( mlab$ DATA[16] )
(It may display better if you take the transpose ( ?t
) and use a wide screen with options(width=150)
... and use round to 3 places.
round( t(dat) , 3)
R building large data frame from file import
Taking into account Roland's suggestion, here is, I guess, a bad way to do it with for loops. I separated the subjects because the object got too large.
subdirs <- list.dirs(".")
for (this_subd in 2:length(subdirs)) {
erpdata <- array(dim = c(200,16,256)) # ERP array
targets <- array(dim = c(200,1)) # Target array
# look for all mat-files in that directory
filelist <- list.files(path = subdirs[this_subd], full.names = FALSE,
pattern = "^.*.mat$",
ignore.case = TRUE, recursive = TRUE,
include.dirs = FALSE)
# combine current subdir path
filelist <- paste(subdirs[this_subd],filelist,sep="/")
# Anonymous function to work over each file and resave as R data
filedatas <- lapply(filelist, function(x) {
curdata <- readMat(con = x)
return(curdata)
})
for (this_file in 2:length(filedatas)) {
this_erp <- filedatas[][[this_file]]$eeg
this_tgt <- this_erp[,,1]$TGT
this_erp <- array(this_erp[,,1]$ERP,dim = c(200,16,256))
erpdata <- abind(erpdata,this_erp,along=1)
targets <- rbind(targets,this_tgt)
}
# Permute the data into samples X channels X trials
erpdata <- aperm(erpdata,c(3,2,1))
# Remove NAs from originally initializing array
erpdata <- array(erpdata[!is.na(erpdata)],dim = dim(erpdata))
targets <- array(targets[!is.na(targets)],dim = dim(targets))
targets <- as.factor(targets) # convert to categorical variable
save(erpdata,targets,
file = paste(subdirs[this_subd],"/",
substring(subdirs[this_subd],first=3),
"unifieddata.Rdata",
sep = "")
)
# cleanup to save memory
rm(erpdata,targets,this_erp,this_tgt)
}
In R, how to convert a list that contains a list and numeric elements into a data frame
Solution (thanks to Ian Campbell):
Note: The column names are wonky, but the data were successfully extracted and exported into a .CSV file!
library(R.matlab)
library(tidyr)
cats <- readMat("cats.mat")
cats2 <- cats$catlist
cats3 <- lapply(cats2, unlist, use.names=TRUE)
cats_for_export <- as.data.frame(cats3)
write.csv(cats_for_export, file="cats.csv")
Related Topics
How to Combine Multiple .CSV Files in R
Arranging Arrows Between Points Nicely in Ggplot2
Ggplot with Customized Font Not Showing Properly on Shinyapps.Io
How to Use a Character Vector of Column Names in the Formula Argument of Dcast (Reshape2)
Replace Rbind in For-Loop with Lapply? (2Nd Circle of Hell)
How to Build a Crossword-Like Plot for a Boolean Matrix
Why Does Lm Run Out of Memory While Matrix Multiplication Works Fine for Coefficients
Specify Position of Geom_Text by Keywords Like "Top", "Bottom", "Left", "Right", "Center"
Loop for Reverse Geocoding in R
Filter Groups in Dplyr That Exclusively Contain Specific Combinations of Values
Margin Adjustments When Using Ggplot's Geom_Tile()
Findassocs for Multiple Terms in R
Match Dataframes Excluding Last Non-Na Value and Disregarding Order
Locator Equivalent in Ggplot2 (For Maps)
Produce a Table Spanning Multiple Pages Using Kable()
Remove Certain Legend Variables and Legend Values from Ggplot2