Reputation: 87
I want to use map to apply a function to each column of a tibble.
However, I don't want the tibble columns to be simplified.
I could deal with that by re-creating tibbles with one column using imap
.
However, how do I do that?
Let's use a super-simple function called test
to see if it works.
Default behavior: columns simplified to vectors:
test<-function(data){
data
}
tibble(v1=1:20,v2=100:119) %>% map(test)
$v1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$v2
[1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
This can't work because the names need to be quoted:
tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(.y=.x))) %>% str
List of 2
$ v1: tibble [20 x 1] (S3: tbl_df/tbl/data.frame)
..$ .y: int [1:20] 1 2 3 4 5 6 7 8 9 10 ...
$ v2: tibble [20 x 1] (S3: tbl_df/tbl/data.frame)
..$ .y: int [1:20] 100 101 102 103 104 105 106 107 108 109 ...
So why does this not work?
tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(!!!(.y)=.x)))
Error: unexpected '=' in "tibble(v1=1:20,v2=100:119) %>% imap(~test(tibble(!!!(.y)="
Upvotes: 2
Views: 299
Reputation: 389275
You can use setNames
:
tibble::tibble(v1=1:20,v2=100:119) %>% purrr::imap(~test(.x) %>% setNames(.y))
#$v1
# A tibble: 20 x 1
# v1
# <int>
# 1 1
# 2 2
# 3 3
# 4 4
# 5 5
#...
#...
#$v2
# A tibble: 20 x 1
# v2
# <int>
# 1 100
# 2 101
# 3 102
# 4 103
# 5 104
# 6 105
#...
#...
Upvotes: 0
Reputation: 887901
We can change the =
to assignment operator (:=
) and evaluate (!!
) the .
y on the lhs of :=
library(tibble)
library(purrr)
out <- tibble(v1=1:20,v2=100:119) %>%
imap( ~ test(tibble(!!.y := .x)))
-output
str(out)
#List of 2
# $ v1: tibble [20 × 1] (S3: tbl_df/tbl/data.frame)
# ..$ v1: int [1:20] 1 2 3 4 5 6 7 8 9 10 ...
# $ v2: tibble [20 × 1] (S3: tbl_df/tbl/data.frame)
# ..$ v2: int [1:20] 100 101 102 103 104 105 106 107 108 109 ...
Upvotes: 1