使用list-columns保存数据框作为csv文件

时间:2017-12-29 14:42:40

标签: r list dplyr tidyverse

我有以下数据框,如下所示(列表为3列)。

A tibble: 14 x 4
                                                    clinic_name drop_in_hours appointment_hours   services
                                                          <chr>        <list>            <list>     <list>
     1                   Birth Control and Sexual Health Centre    <list [1]>        <list [1]> <list [1]>
     2 Black Creek Community Health Centre (Sheridan Mall Site)    <list [1]>        <list [1]> <list [1]>
     3 Black Creek Community Health Centre (Yorkgate mall Site)    <list [1]>        <list [1]> <list [1]>
     4                                         Crossways Clinic    <list [1]>        <list [1]> <list [1]>
     5                                       Hassle Free Clinic    <list [1]>        <list [1]> <list [1]>
     6                          Immigrant Women's Health Center    <list [1]>        <list [1]> <list [1]>
     7                          Rexdale Community Health Center    <list [1]>        <list [1]> <list [1]>
     8                            Rexdale Youth Resource Center    <list [1]>        <list [1]> <list [1]>
     9                         Scarborough Sexual Health Clinic    <list [1]>        <list [1]> <list [1]>
    10                                 Special Treatment Clinic    <list [1]>        <list [1]> <list [1]>
    11                            Taibu Community Health Center    <list [1]>        <list [1]> <list [1]>
    12                                                 The Gate    <list [1]>        <list [1]> <list [1]>
    13                                   The Jane Street Clinic    <list [1]>        <list [1]> <list [1]>
    14                                            The Talk Shop    <list [1]>        <list [1]> <list [1]>

我想将其输出为csv文件。我注意到数据框的列不应该是R中的列表。所以我做了一些google并找到了这个save data.frames with list-column所以我试了一下:

library(tidyverse)

df %>% 
  mutate(drop_in_hours = map_chr(drop_in_hours, ~ capture.output(dput(.))),
         appointment_hours = map_chr(appointment_hours, ~ capture.output(dput(.))),
         services = map_chr(services, ~ capture.output(dput(.)))     ) %>% 
  write_csv("health.csv")

但是我收到了一个错误,我在这里错过了一些东西吗?

Error in mutate_impl(.data, dots) : 
  Evaluation error: Result 4 is not a length 1 atomic vector

4 个答案:

答案 0 :(得分:4)

创建包含列表列的tibble:

cancelAndHoldAtTime

enter image description here

编写一个将任何列表列转换为字符类型的通用函数:

library(tibble)

clinic_name <- c('bobo center', 'yoyo plaza', 'lolo market')
drop_in_hours <- list(c("Monday: 2 pm - 5 pm", "Tuesday: 4 pm - 7 pm")) 
appointment_hours <- list(c("Monday: 1 pm - 2 pm", "Tuesday: 2 pm - 3 pm")) 
services <- list(c("skin graft", "chicken heart replacement"))

tibb <- data_frame(clinic_name, drop_in_hours, appointment_hours, services)

print(tibb)

将功能应用于与列表列同步:

set_lists_to_chars <- function(x) {
    if(class(x) == 'list') {
    y <- paste(unlist(x[1]), sep='', collapse=', ')
    } else {
    y <- x 
    }
    return(y)
}

enter image description here

将新格式化的数据框写为csv文件:

new_frame <- data.frame(lapply(tibb, set_lists_to_chars), stringsAsFactors = F)

new_frame

enter image description here

这是一个csv文件,列表列扩展为常规字符串。

这是一个包罗万象的功能。只需传递你的tibble和文件名:

write.csv(new_frame, file='Desktop/clinics.csv')

<强>用法:

tibble_with_lists_to_csv <- function(tibble_object, file_path_name) {
    set_lists_to_chars <- function(x) { 
        if(class(x) == 'list') { y <- paste(unlist(x[1]), sep='', collapse=', ') } else { y <- x  } 
        return(y) }
    new_frame <- data.frame(lapply(tibb, set_lists_to_chars), stringsAsFactors = F)
    write.csv(new_frame, file=file_path_name)
}

答案 1 :(得分:1)

您是否有任何特定原因要将列保存为列表?或者,您可以使用unnest并将其保存在csv中。以下示例

library(tidyverse)
df_list<-data_frame(abc = letters[1:3], lst = list(1:3, 1:3, 1:3))
df_list %>% unnest() %>% write.csv("list.csv")

此外,当您阅读文件时,您可以nest将其恢复

df <- read.csv("list.csv")[ ,2:3]
df %>% nest(lst)

答案 2 :(得分:1)

exploratory::list_to_text()会将list列转换为character列。默认值为sep = ", ",如果写入.csv,我建议将其更改为其他内容。

devtools::install_github("exploratory-io/exploratory_func")

list_to_text <- function(column, sep = ", "){
  loadNamespace("stringr")
  ret <- sapply(column, function(x) {
    ret <- stringr::str_c(x, collapse = sep)
    if(identical(ret, character(0))){
      # if it's character(0)
      NA
    } else {
      ret
    }
  })
  as.character(ret)
}

https://github.com/exploratory-io/exploratory_func/blob/master/LICENSE.md

答案 3 :(得分:1)

这是另一个可能更简单的选择。

根据数据,逗号分隔的值可能会变得复杂,因此我使用了条形|来分隔列表列中的值:

library(tidyverse)

starwars %>% 
  rowwise() %>% 
  mutate_if(is.list, ~paste(unlist(.), collapse = '|')) %>% 
  write.csv('df_starwars.csv', row.names = FALSE)

starwarsdplyr示例数据帧之一。