user113156
user113156

Reputation: 7127

map over list columns and extract the first list item

I have the following data which looks like:

# A tibble: 6 × 2
  `Total_ Española_Porcentaje` `Total_ Extranjero_Porcentaje`
  <list>                       <list>                        
1 <dbl [3]>                    <dbl [3]>                     
2 <dbl [3]>                    <dbl [3]>                     
3 <dbl [3]>                    <dbl [3]>                     
4 <dbl [3]>                    <dbl [3]>                     
5 <dbl [3]>                    <dbl [3]>                     
6 <dbl [3]>                    <dbl [3]> 

I am trying to map over the columns using map and extract the first dbl.

I have tried

df %>%
  map_dbl(., ~if(length(.x)) .x[1] else NA)

and

df %>%
  imap_dfc(., function(x, y) 
    tibble(!!y := map_dbl(x, ~if(length(.x)) .x[1] else NA)))

But I can't get it to work.

Data <- structure(list(`Total_ Española_Porcentaje` = list(c(5.9, 5.9, 
5.9), c(5.9, 5.9, 5.9), c(5.9, 5.9, 5.9), c(5.9, 5.9, 5.9), c(5.9, 
5.9, 5.9), c(5.9, 5.9, 5.9)), `Total_ Extranjero_Porcentaje` = list(
    c(5.9, 5.9, 5.9), c(5.9, 5.9, 5.9), c(5.9, 5.9, 5.9), c(5.9, 
    5.9, 5.9), c(5.9, 5.9, 5.9), c(5.9, 5.9, 5.9))), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))

Upvotes: 3

Views: 655

Answers (3)

TarJae
TarJae

Reputation: 79164

Maybe we can use pluck from purrr package:

pluck() implement a generalised form of [[ that allow you to index deeply and flexibly into data structures. https://purrr.tidyverse.org/reference/pluck.html

library(purrr)
pluck(Data, 1)

Output:

 pluck(2,2)
[1] 5.9 5.9 5.9
> pluck(Data,1)
[[1]]
[1] 5.9 5.9 5.9

[[2]]
[1] 5.9 5.9 5.9

[[3]]
[1] 5.9 5.9 5.9

[[4]]
[1] 5.9 5.9 5.9

[[5]]
[1] 5.9 5.9 5.9

[[6]]
[1] 5.9 5.9 5.9

Upvotes: 3

akrun
akrun

Reputation: 887531

We can use across to loop over the list columns, then map over the elements of the list, if the length is greater than 0, select the first element or else returns NA

library(dplyr)
library(purrr)
Data %>%
      mutate(across(everything(), 
       ~ map_dbl(., ~ if(length(.x) ) first(.x) else NA)))
# A tibble: 6 x 2
  `Total_ Española_Porcentaje` `Total_ Extranjero_Porcentaje`
                         <dbl>                          <dbl>
1                          5.9                            5.9
2                          5.9                            5.9
3                          5.9                            5.9
4                          5.9                            5.9
5                          5.9                            5.9
6                          5.9                            5.9

Or as inspired from @ThomasIsCoding

map_dfr(Data, map_dbl, first)
# A tibble: 6 x 2
  `Total_ Española_Porcentaje` `Total_ Extranjero_Porcentaje`
                         <dbl>                          <dbl>
1                          5.9                            5.9
2                          5.9                            5.9
3                          5.9                            5.9
4                          5.9                            5.9
5                          5.9                            5.9
6                          5.9                            5.9

Upvotes: 3

ThomasIsCoding
ThomasIsCoding

Reputation: 102309

A base R trick

> Data[] <- lapply(Data, sapply, `[`, 1)
> Data
# A tibble: 6 x 2
  `Total_ Espa±ola_Porcentaje` `Total_ Extranjero_Porcentaje`
                         <dbl>                          <dbl>
1                          5.9                            5.9
2                          5.9                            5.9
3                          5.9                            5.9
4                          5.9                            5.9
5                          5.9                            5.9
6                          5.9                            5.9

Upvotes: 2

Related Questions