6

I have this data set

df<-
structure(list(x = list(structure(c(1.2956002895122, 0.84856971403248, 
0.318587376385379, 1.52311609250527, 0.761866777256873, 1.34942921531382, 
1.32182157459345, 0.164293091865351, 1.33391849692185, 1.1741444035705
), dim = c(5L, 2L), dimnames = list(NULL, c("Consumption", "Income"
))), structure(c(0.84804804783009, 0.454659301099081, -0.785771762432506, 
0.746346341726964, 1.07546066123554, 2.36782435778472, 0.33145722604832, 
-1.16704208085918, -0.505189833907774, -0.0305510764003426), dim = c(5L, 
2L), dimnames = list(NULL, c("Consumption", "Income"))), structure(c(1.67206824624292, 
0.621301929142792, -2.64748116335658, 1.06382925864556, 0.481820198662883, 
0.977532978223718, 0.12858898496739, -0.929583796669093, 1.03055091162915, 
1.75054296893639), dim = c(5L, 2L), dimnames = list(NULL, c("Consumption", 
"Income"))), structure(c(1.06124884050636, 1.5695107316969, -0.71012903796485, 
0.697670432455871, 0.441910553257345, 1.131314331505, 1.58797564122333, 
-0.0245687154568635, 1.26341241328479, -0.701603888772303), dim = c(5L, 
2L), dimnames = list(NULL, c("Consumption", "Income"))), structure(c(-0.320387157182086, 
0.909612038039385, -0.30534801455308, 0.13028454605271, 1.04548318778476, 
0.744569146062672, 0.157712771975432, -0.47140382117885, -0.757295165153137, 
1.30319365700164), dim = c(5L, 2L), dimnames = list(NULL, c("Consumption", 
"Income"))), structure(c(1.1328615935615, 1.18848732447009, -1.19259137763868, 
1.61383333543976, 0.112684975627695, -0.294284500868068, 0.653900926135023, 
0.0179116410157527, 2.3485206187256, 0.561897344846424), dim = c(5L, 
2L), dimnames = list(NULL, c("Consumption", "Income"))), structure(c(0.97523495340453, 
2.13698353093441, 0.766663720261808, 0.693029332670238, 0.704645561153127, 
1.29154523355534, 4.14154953485982, -0.454659021170493, 0.55475024788991, 
0.63410937974327), dim = c(5L, 2L), dimnames = list(NULL, c("Consumption", 
"Income"))))), row.names = c(NA, -7L), class = "data.frame")

How can I put this to a data frame? Right now each row is considered as 1 value and I can not access the elements of each row.

0

5 Answers 5

8

Your df has list columns where each row contains a matrix. So you need to unpack them. Here's an approach that gives you a tidy dataframe:

do.call(rbind, lapply(seq_along(df$x), function(i) {
  data.frame(group = i, df$x[[i]])
}))

#>    group Consumption      Income
#> 1      1   1.2956003  1.34942922
#> 2      1   0.8485697  1.32182157
#> 3      1   0.3185874  0.16429309
#> 4      1   1.5231161  1.33391850
#> 5      1   0.7618668  1.17414440
#> ...
#> 30     6   0.1126850  0.56189734
#> 31     7   0.9752350  1.29154523
#> 32     7   2.1369835  4.14154953
#> 33     7   0.7666637 -0.45465902
#> 34     7   0.6930293  0.55475025
#> 35     7   0.7046456  0.63410938

Created on 2026-04-03 with reprex v2.1.1

or using {dplyr}:

library(dplyr)

df |>
  mutate(group = row_number()) |>
  reframe(
    group = group,
    as.data.frame(x),
    .by = group
  )

If you want it in wide format:

library(tidyverse)

df |>
  mutate(group = row_number(), .before = 1,
         x = map(x, ~set_names(c(.x), 
                               paste0(rep(colnames(.x), each = nrow(.x)), "_", 
                                      rep(seq_len(nrow(.x)), ncol(.x)))))) |>
  unnest_wider(x)
#> # A tibble: 7 × 11
#>   group Consumption_1 Consumption_2 Consumption_3 Consumption_4 Consumption_5
#>   <int>         <dbl>         <dbl>         <dbl>         <dbl>         <dbl>
#> 1     1         1.30          0.849         0.319         1.52          0.762
#> 2     2         0.848         0.455        -0.786         0.746         1.08 
#> 3     3         1.67          0.621        -2.65          1.06          0.482
#> 4     4         1.06          1.57         -0.710         0.698         0.442
#> 5     5        -0.320         0.910        -0.305         0.130         1.05 
#> 6     6         1.13          1.19         -1.19          1.61          0.113
#> 7     7         0.975         2.14          0.767         0.693         0.705
#> # ℹ 5 more variables: Income_1 <dbl>, Income_2 <dbl>, Income_3 <dbl>,
#> #   Income_4 <dbl>, Income_5 <dbl>

Created on 2026-04-03 with reprex v2.1.1

Or in {base}:

data.frame(
  group = seq_len(nrow(df)),
  do.call(rbind, lapply(df$x, function(m) {
    setNames(
      c(m), 
      paste0(rep(colnames(m), each = nrow(m)), "_", 
             rep(seq_len(nrow(m)), ncol(m)))
    )
  }))
)
Sign up to request clarification or add additional context in comments.

Comments

8

With {collapse}

collapse::unlist2d(l=df$x)

e.g.

collapse::unlist2d(l=df$x) |>  
  head()
  .id Consumption    Income
1   1   1.2956003 1.3494292
2   1   0.8485697 1.3218216
3   1   0.3185874 0.1642931
4   1   1.5231161 1.3339185
5   1   0.7618668 1.1741444
6   2   0.8480480 2.3678244

With idcols-argument we can specify the name (defaults to .id). {collapse} is generally considered a rapidfly fast package, it also ships collapse::pivot-function for reshaping.

With {base} (from R Core)

If the group column (.id) is not needed, simply

df$x |> 
  do.call(what='rbind') |> 
  as.data.frame.matrix()

If needed, I tend to use a Map + [<- construct like

df$x |>
  lapply(data.frame) |> 
  ( \(.) Map(`[<-`, ., '.id', value=seq_along(df$x)) )() |> 
  do.call(what='rbind')

For wide format

data.frame(df$x)
## calls `as.data.frame()` which has `.list`-method
  Consumption    Income Consumption.1    Income.1 Consumption.2   Income.2 Consumption.3    Income.3 Consumption.4   Income.4 Consumption.5    Income.5 Consumption.6   Income.6
1   1.2956003 1.3494292     0.8480480  2.36782436     1.6720682  0.9775330     1.0612488  1.13131433    -0.3203872  0.7445691      1.132862 -0.29428450     0.9752350  1.2915452
2   0.8485697 1.3218216     0.4546593  0.33145723     0.6213019  0.1285890     1.5695107  1.58797564     0.9096120  0.1577128      1.188487  0.65390093     2.1369835  4.1415495
3   0.3185874 0.1642931    -0.7857718 -1.16704208    -2.6474812 -0.9295838    -0.7101290 -0.02456872    -0.3053480 -0.4714038     -1.192591  0.01791164     0.7666637 -0.4546590
4   1.5231161 1.3339185     0.7463463 -0.50518983     1.0638293  1.0305509     0.6976704  1.26341241     0.1302845 -0.7572952      1.613833  2.34852062     0.6930293  0.5547502
5   0.7618668 1.1741444     1.0754607 -0.03055108     0.4818202  1.7505430     0.4419106 -0.70160389     1.0454832  1.3031937      0.112685  0.56189734     0.7046456  0.6341094

might be enough.


Notes

  1. df <- <sth> masks stats::df-function which ships with R Core. From the head of the corresponding help file

FDist {stats} R Documentation The F Distribution Description Density, distribution function, quantile function and random generation for the F distribution with df1 and df2 degrees of freedom (and optional non-centrality parameter ncp). Usage df(x, df1, df2, ncp, log = FALSE) ...

Therefore, I recommend to assign to either metasyntactic variable names, e.g. foobar, foo, bar, baz, quux, xyzzy, ...,--personally I like .data, x, X those are rather R-specific--or something data-specific, e.g. cshd for cross-sectional household data.

  1. Where does the data come from? It’s possible there’s an issue with the import process, and we may currently be dealing with an XY-problem.

  2. Some tidy data references would encourage us to keep the data in long format. A well-known source.

Comments

4

Using unlist with as.data.frame

as.data.frame(unlist(df, recursive = FALSE))

output:

  x1.Consumption x1.Income x2.Consumption   x2.Income x3.Consumption  x3.Income
1      1.2956003 1.3494292      0.8480480  2.36782436      1.6720682  0.9775330
2      0.8485697 1.3218216      0.4546593  0.33145723      0.6213019  0.1285890
3      0.3185874 0.1642931     -0.7857718 -1.16704208     -2.6474812 -0.9295838
4      1.5231161 1.3339185      0.7463463 -0.50518983      1.0638293  1.0305509
5      0.7618668 1.1741444      1.0754607 -0.03055108      0.4818202  1.7505430
  x4.Consumption   x4.Income x5.Consumption  x5.Income x6.Consumption
1      1.0612488  1.13131433     -0.3203872  0.7445691       1.132862
2      1.5695107  1.58797564      0.9096120  0.1577128       1.188487
3     -0.7101290 -0.02456872     -0.3053480 -0.4714038      -1.192591
4      0.6976704  1.26341241      0.1302845 -0.7572952       1.613833
5      0.4419106 -0.70160389      1.0454832  1.3031937       0.112685
    x6.Income x7.Consumption  x7.Income
1 -0.29428450      0.9752350  1.2915452
2  0.65390093      2.1369835  4.1415495
3  0.01791164      0.7666637 -0.4546590
4  2.34852062      0.6930293  0.5547502
5  0.56189734      0.7046456  0.6341094

Comments

4

With base R you can use basic operations like cbind + rep + nrow + rbind + Reduce

with(df,
     cbind(
      data.frame(grp = rep(seq_along(x), lapply(x,nrow))),
      Reduce(rbind,x)))

which gives

   grp Consumption      Income
1    1   1.2956003  1.34942922
2    1   0.8485697  1.32182157
3    1   0.3185874  0.16429309
4    1   1.5231161  1.33391850
5    1   0.7618668  1.17414440
6    2   0.8480480  2.36782436
7    2   0.4546593  0.33145723
8    2  -0.7857718 -1.16704208
9    2   0.7463463 -0.50518983
10   2   1.0754607 -0.03055108
11   3   1.6720682  0.97753298
12   3   0.6213019  0.12858898
13   3  -2.6474812 -0.92958380
14   3   1.0638293  1.03055091
15   3   0.4818202  1.75054297
16   4   1.0612488  1.13131433
17   4   1.5695107  1.58797564
18   4  -0.7101290 -0.02456872
19   4   0.6976704  1.26341241
20   4   0.4419106 -0.70160389
21   5  -0.3203872  0.74456915
22   5   0.9096120  0.15771277
23   5  -0.3053480 -0.47140382
24   5   0.1302845 -0.75729517
25   5   1.0454832  1.30319366
26   6   1.1328616 -0.29428450
27   6   1.1884873  0.65390093
28   6  -1.1925914  0.01791164
29   6   1.6138333  2.34852062
30   6   0.1126850  0.56189734
31   7   0.9752350  1.29154523
32   7   2.1369835  4.14154953
33   7   0.7666637 -0.45465902
34   7   0.6930293  0.55475025
35   7   0.7046456  0.63410938

Another interesting way of presenting the dataframe format might be

do.call(Reduce, c(cbind,df))

which gives

     Consumption    Income Consumption      Income Consumption     Income
[1,]   1.2956003 1.3494292   0.8480480  2.36782436   1.6720682  0.9775330
[2,]   0.8485697 1.3218216   0.4546593  0.33145723   0.6213019  0.1285890
[3,]   0.3185874 0.1642931  -0.7857718 -1.16704208  -2.6474812 -0.9295838
[4,]   1.5231161 1.3339185   0.7463463 -0.50518983   1.0638293  1.0305509
[5,]   0.7618668 1.1741444   1.0754607 -0.03055108   0.4818202  1.7505430
     Consumption      Income Consumption     Income Consumption      Income
[1,]   1.0612488  1.13131433  -0.3203872  0.7445691    1.132862 -0.29428450
[2,]   1.5695107  1.58797564   0.9096120  0.1577128    1.188487  0.65390093
[3,]  -0.7101290 -0.02456872  -0.3053480 -0.4714038   -1.192591  0.01791164
[4,]   0.6976704  1.26341241   0.1302845 -0.7572952    1.613833  2.34852062
[5,]   0.4419106 -0.70160389   1.0454832  1.3031937    0.112685  0.56189734
     Consumption     Income
[1,]   0.9752350  1.2915452
[2,]   2.1369835  4.1415495
[3,]   0.7666637 -0.4546590
[4,]   0.6930293  0.5547502
[5,]   0.7046456  0.6341094

Comments

3

If you use the dplyr package, there is an even shorter and more readable way to achieve the exact same result:

library(dplyr)

# Convert matrices to data frames and bind them together, 

# automatically creating an ID column for the groups

clean_df <- bind_rows(lapply(df$x, as.data.frame), .id = "group")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.