R: записать список списков списков в текстовый файл с именами - PullRequest
0 голосов
/ 18 октября 2018

У меня есть список списков со следующей структурой:

a = list("t" = list('abc'), "c" = list('def','ghi')) 
b = list("t" = list('jk','kl'), "c" = list('lmn')) 
c = list("t" = list('op','pq','z'), "c" = list('qrs','tuv','wxy'))
ls = list('one'=a,'two'=b,'three'=c)

Мне нужно сохранить это в текстовом файле.Поскольку не все элементы имеют одинаковую длину, мне нужно заполнить nans, прежде чем превратить его в кадр данных и записать в файл.Мне нужен файл, который выглядит примерно так (здесь он показан примерно как .csv, но хорошо подходит .txt):

 t1, t2, t3, c1, c2, c3
one,abc,nan,nan,def,ghi,nan
two,jk,kl,nan,lmn,nan,nan
three,op,pq,z,qrs,tuv,wxy

Я новичок в R, поэтому у меня есть только общее представление о том, как я могусделать это и не могу понять синтаксис.Примерно так в псевдокоде:

lapply(ls, fill nans)
lapply(ls, unlist)
lapply(ls, names=[t1,t2,t3,c1,c2,c3])
df=data.frame(ls)
write.table(df)

Может ли кто-нибудь провести меня через это?

Редактировать: я смог добиться некоторого прогресса с:

ellength <- function(ls,i) {return(length(ls[[i]]))}

fillna <- function(ls,i,m) {
if (length(ls[[i]])<m) {
return(append(ls[[i]],vector('list',length=m-length(ls[[i]]))))
}
else {return(ls[[i]])}
}

make_col <- function(ls,i){
return(lapply(ls,fillna,i=i,m=max(unlist(lapply(ls,ellength,i=i)))))
}

> matrix(list(make_col(ls,'t'),make_col(ls,'c')))
     [,1]  
[1,] List,3
[2,] List,3

Но ядо сих пор не могу записать это в файл каким-либо связным способом.Это так просто сделать в Python;Я должен что-то упустить.Помощь

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Рассмотрите возможность создания списка фреймов данных после распечатки вложенного списка:

char_vec <- unlist(ls)

df_list <- lapply(names(ls), function(x) {
  tmp <- data.frame(t(char_vec[names(char_vec)[grep(x, names(char_vec))]]),
                    stringsAsFactors = FALSE)
  names(tmp) <- gsub(".*\\.", "", names(tmp))

  return(tmp)
})

df_list
# [[1]]
#     t  c1  c2
# 1 abc def ghi

# [[2]]
#   t1 t2   c
# 1 jk kl lmn

# [[3]]
#   t1 t2 t3  c1  c2  c3
# 1 op pq  z qrs tuv wxy

Чтобы связать все элементы фрейма данных вместе, вы можете использовать dplyr, data.table или даже base R:

dplyr bind_rows)

final_df1 <- bind_rows(df_list)

# CLEAN UP AND RE-ORDER COLUMNS
final_df1 <- transform(final_df1, 
                       t1 = ifelse(is.na(t), t1, t),
                       t = NULL,
                       c1 = ifelse(is.na(c), c1, c),
                       c = NULL
              )

final_df1 <- final_df1[order(names(final_df1))]

data.table rbindlist)

final_df2 <- data.frame(rbindlist(df_list, fill=TRUE))

# CLEAN UP AND RE-ORDER COLUMNS
final_df2 <- transform(final_df2, 
                       t1 = ifelse(is.na(t), t1, t),
                       t = NULL,
                       c1 = ifelse(is.na(c), c1, c),
                       c = NULL
              )

final_df2 <- final_df2[order(names(final_df2))]

база R do.call)

# RETRIEVE ALL COLUMN NAMES
nms <- names(unlist(df_list))

df_list <- lapply(df_list, function(df){
  # CREATE BLANK COLUMNS FOR rbind
  for(i in nms) {
    if(!i %in% names(df)) {
      df[[i]] <- NA
    }
  }

  # CLEAN UP AND RE-ORDER COLUMNS
  df <- within(df, {t1 <- ifelse(is.na(t), t1, t)
                    t <- NULL
                    c1 <- ifelse(is.na(c), c1, c)
                    c <- NULL
        })

  return(df[order(names(df))])
})

final_df3 <- do.call(rbind, df_list)

Выход

final_df1
#    c1   c2   c3  t1   t2   t3
# 1 def  ghi <NA> abc <NA> <NA>
# 2 lmn <NA> <NA>  jk   kl <NA>
# 3 qrs  tuv  wxy  op   pq    z

identical(final_df1, final_df2)
# [1] TRUE
identical(final_df1, final_df3)
# [1] TRUE
identical(final_df2, final_df3)
# [1] TRUE
0 голосов
/ 18 октября 2018

Помогает ли это вообще?

library(tidyr)
library(dplyr)
a = list("t" = 'abc', "c" = list('def','ghi')) 
b = list("t" = 'jk', "c" = list('lmn')) 
c = list("t" = 'op', "c" = list('qrs','tuv','wxy'))
ls = list('one'=a,'two'=b,'three'=c)
#unlist and turn into a df
lx <- as.data.frame( unlist(ls),stringsAsFactors = FALSE)
#make rownames as column
lx$nms <- rownames(lx)

#split nms column so you can transpose your data
lx <- separate(lx, nms, c("v1","v2"), sep = "[.]")
lx <- mutate(lx, v3 = `unlist(ls)`) %>% 
      select(-`unlist(ls)`)
#transpose your data - it fills with NA
#NaN is a numeric field so you can't use it to fill character variables
lx2 <- spread(lx,v2,v3)

update

Если вы хотите свернуть переменные, вы можете использовать ifelse для замены NA s в определенных столбцах:

lx2 <- mutate(lx2, c_1 = ifelse(is.na(c),c1,c))
lx2 <- mutate(lx2, t_1 = ifelse(is.na(t),t1,t))
lx3 <- lx2[c('v1','c_1','c2','c3','t_1','t2','t3')] 
...