2

Suppose I have the following dataframe:

  | a | b | c |
x | 1 | 2 | 3 |
y | 4 | 5 | 6 |
z | 7 | 8 | 9 |

I would like to convert it into a list by row, with each containing a named vector, which is basically the equivalent of the output of list(x=c(a=1,b=2,c=3), y=c(a=4,b=5,c=6), x=c(a=7,b=8,c=9)):

$x
a b c 
1 2 3 

$y
a b c 
4 5 6 

$x
a b c 
7 8 9 

How would I go about doing this?

Cenoc
  • 11,172
  • 21
  • 58
  • 92

2 Answers2

5

We can use

res <- lapply(split(df1, row.names(df1)), unlist)
str(res)
#List of 3
#$ x: Named int [1:3] 1 2 3
#  ..- attr(*, "names")= chr [1:3] "a" "b" "c"
#$ y: Named int [1:3] 4 5 6
# ..- attr(*, "names")= chr [1:3] "a" "b" "c"
#$ z: Named int [1:3] 7 8 9
# ..- attr(*, "names")= chr [1:3] "a" "b" "c"
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Thank you! But the result isn't a list of named vectors, and the list keys are just the numbers rather than the rownames. – Cenoc Jul 23 '16 at 14:30
  • @Cenoc I changed the code a bit. Do you still think it isn't a list of named vectors? – akrun Jul 23 '16 at 14:41
2

I'm a big fan of of using the purrr package for these sorts of tasks:

df <- read.table(text = "   a  b  c
                     x  1  2  3 
                     y  4  5  6 
                     z  7  8  9", header = TRUE)

library(purrr)

df_as_list <- set_names(by_row(df, ~ unlist(.x), .collate = "list")$.out, rownames(df))

df_as_list  

# $x
# a b c 
# 1 2 3 
# 
# $y
# a b c 
# 4 5 6 
# 
# $z
# a b c 
# 7 8 9 

typeof(df_as_list$x)
# [1] "integer"

As the name suggests by_row cycles through df by row, in this case applying unlist(a_row) to each row, which returns it as a vector. As we want the output as a list .collate is set to "list". We return the list, .out, and then name it as required (as the names are not naturally preserved).

Alex Ioannides
  • 1,204
  • 9
  • 10