I have the following data frame that looks like this (3 columns as list).
A tibble: 14 x 4
clinic_name drop_
Here's another option that may be a little simpler.
Depending on the data, comma separated values could get complicated, so I'm using a bar |
for separating values in list columns:
library(tidyverse)
starwars %>%
rowwise() %>%
mutate_if(is.list, ~paste(unlist(.), collapse = '|')) %>%
write.csv('df_starwars.csv', row.names = FALSE)
starwars
is one of the dplyr
sample dataframes.
exploratory::list_to_text()
will convert a list
column to a character
column. The default is sep = ", "
, which I recommend changing to something else if writing to a .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
Create a tibble containing list columns:
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)
Write a general-purpose function that converts any list columns to character type:
set_lists_to_chars <- function(x) {
if(class(x) == 'list') {
y <- paste(unlist(x[1]), sep='', collapse=', ')
} else {
y <- x
}
return(y)
}
Apply function to tibble with list columns:
new_frame <- data.frame(lapply(tibb, set_lists_to_chars), stringsAsFactors = F)
new_frame
Write newly formatted dataframe as csv file:
write.csv(new_frame, file='Desktop/clinics.csv')
This is a csv file with the list columns expanded as regular strings.
Here is an all-encompassing function. Just pass in your tibble and a filename:
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(tibble_object, set_lists_to_chars), stringsAsFactors = F)
write.csv(new_frame, file=file_path_name)
}
Usage:
tibble_with_lists_to_csv(tibb, '~/Desktop/tibb.csv')
I had a similar dataframe with list columns that I wanted to save as csv. I figured out this method. As well as how to turn the columns back into lists.
library(tidyverse)
# create a df with a list column
df <- tibble(x=rep(1:5,each=2), y=LETTERS[1:10]) %>%
group_by(x) %>%
summarise(z=list(y))
# this throws an error
write_csv(df, "test.csv")
# convert the list column to a string
df2 <- df %>%
group_by(x) %>% # where x==unique(x)
mutate(z=paste(z))
# this works
write_csv(df2, "test.csv")
# read the csv
df3 <- read_csv("test.csv")
# reconstruct original df by parsing the strings
# https://stackoverflow.com/questions/1743698/evaluate-expression-given-as-a-string
df4 <- df3 %>%
group_by(x) %>%
mutate(z=list(eval(parse(text=z))))
Is there any specific reason why you would like to save the columns as a list ? Alternatively, you can use unnest
and save it in csv. example below
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")
further, when you read the file you can nest
it back
df <- read.csv("list.csv")[ ,2:3]
df %>% nest(lst)