0

In the following code, I defined a tibble df with two columns: name column contains a character vector of c("a", "b", "c"), and data column contains a list of tibbles, each with the column value. Then I'd like to change the column name of each tibble's value column to the character in the corresponding row, e.g. "a", "b" and "c". To manipulate the tibble in a row-wise manner, I used dplyr::rowwise(), but then I found that the changes taking effect on the first element (changing the column name to "a") also took effect on the rest of the elements (since after the first row, the printed tibble before the change of the column name showed the column name of "a"). And therefore, it can be expected that the change of column names to the following elements in the column failed, since there were no longer column names of "value" (all changed to "a"). Do I have to use a purrr::map() function here instead of the tidier row-wise tibble manipulation?

Would you please give me an answer using rowwise-mutate_at method? Thanks.

library(tidyverse)
#> Warning: 程辑包'tidyverse'是用R版本3.6.3 来建造的
#> Warning: 程辑包'ggplot2'是用R版本3.6.1 来建造的
#> Warning: 程辑包'tibble'是用R版本3.6.3 来建造的
#> Warning: 程辑包'tidyr'是用R版本3.6.1 来建造的
#> Warning: 程辑包'readr'是用R版本3.6.1 来建造的
#> Warning: 程辑包'purrr'是用R版本3.6.1 来建造的
#> Warning: 程辑包'dplyr'是用R版本3.6.3 来建造的
#> Warning: 程辑包'stringr'是用R版本3.6.1 来建造的
#> Warning: 程辑包'forcats'是用R版本3.6.3 来建造的

df <- tibble::tibble(name = c("a", "b", "c"),
                     data = list(tibble::tibble(value = 1:10)))

df_mutate <- df %>%
  dplyr::rowwise() %>%
  dplyr::mutate_at("data", ~ {
    print(.x)
    colnames(.x)[colnames(.x) %in% "value"] <- name
    list(.x)
  }) %>%
  dplyr::ungroup()
#> # A tibble: 10 x 1
#>    value
#>    <int>
#>  1     1
#>  2     2
#>  3     3
#>  4     4
#>  5     5
#>  6     6
#>  7     7
#>  8     8
#>  9     9
#> 10    10
#> # A tibble: 10 x 1
#>        a
#>    <int>
#>  1     1
#>  2     2
#>  3     3
#>  4     4
#>  5     5
#>  6     6
#>  7     7
#>  8     8
#>  9     9
#> 10    10
#> # A tibble: 10 x 1
#>        a
#>    <int>
#>  1     1
#>  2     2
#>  3     3
#>  4     4
#>  5     5
#>  6     6
#>  7     7
#>  8     8
#>  9     9
#> 10    10

Created on 2020-06-19 by the reprex package (v0.3.0)

devtools::session_info()
#> - Session info ---------------------------------------------------------------
#>  setting  value                         
#>  version  R version 3.6.0 (2019-04-26)  
#>  os       Windows Server x64            
#>  system   x86_64, mingw32               
#>  ui       RTerm                         
#>  language (EN)                          
#>  collate  Chinese (Simplified)_China.936
#>  ctype    Chinese (Simplified)_China.936
#>  tz       Asia/Taipei                   
#>  date     2020-06-19                    
#> 
#> - Packages -------------------------------------------------------------------
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.6.1)
#>  backports     1.1.5   2019-10-02 [1] CRAN (R 3.6.1)
#>  broom         0.5.6   2020-04-20 [1] CRAN (R 3.6.3)
#>  callr         3.4.0   2019-12-09 [1] CRAN (R 3.6.2)
#>  cellranger    1.1.0   2016-07-27 [1] CRAN (R 3.6.1)
#>  cli           2.0.2   2020-02-28 [1] CRAN (R 3.6.3)
#>  colorspace    1.4-1   2019-03-18 [1] CRAN (R 3.6.1)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 3.6.1)
#>  DBI           1.1.0   2019-12-15 [1] CRAN (R 3.6.2)
#>  dbplyr        1.4.2   2019-06-17 [1] CRAN (R 3.6.3)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 3.6.1)
#>  devtools      2.2.1   2019-09-24 [1] CRAN (R 3.6.1)
#>  digest        0.6.23  2019-11-23 [1] CRAN (R 3.6.2)
#>  dplyr       * 1.0.0   2020-05-29 [1] CRAN (R 3.6.3)
#>  ellipsis      0.3.0   2019-09-20 [1] CRAN (R 3.6.1)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 3.6.1)
#>  fansi         0.4.0   2018-10-05 [1] CRAN (R 3.6.1)
#>  forcats     * 0.5.0   2020-03-01 [1] CRAN (R 3.6.3)
#>  fs            1.3.1   2019-05-06 [1] CRAN (R 3.6.1)
#>  generics      0.0.2   2018-11-29 [1] CRAN (R 3.6.1)
#>  ggplot2     * 3.2.1   2019-08-10 [1] CRAN (R 3.6.1)
#>  glue          1.4.1   2020-05-13 [1] CRAN (R 3.6.3)
#>  gtable        0.3.0   2019-03-25 [1] CRAN (R 3.6.1)
#>  haven         2.2.0   2019-11-08 [1] CRAN (R 3.6.3)
#>  highr         0.8     2019-03-20 [1] CRAN (R 3.6.1)
#>  hms           0.5.2   2019-10-30 [1] CRAN (R 3.6.2)
#>  htmltools     0.4.0   2019-10-04 [1] CRAN (R 3.6.1)
#>  httr          1.4.1   2019-08-05 [1] CRAN (R 3.6.1)
#>  jsonlite      1.6     2018-12-07 [1] CRAN (R 3.6.1)
#>  knitr         1.26    2019-11-12 [1] CRAN (R 3.6.2)
#>  lattice       0.20-38 2018-11-04 [2] CRAN (R 3.6.0)
#>  lazyeval      0.2.2   2019-03-15 [1] CRAN (R 3.6.1)
#>  lifecycle     0.2.0   2020-03-06 [1] CRAN (R 3.6.3)
#>  lubridate     1.7.4   2018-04-11 [1] CRAN (R 3.6.2)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 3.6.1)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 3.6.1)
#>  modelr        0.1.6   2020-02-22 [1] CRAN (R 3.6.3)
#>  munsell       0.5.0   2018-06-12 [1] CRAN (R 3.6.1)
#>  nlme          3.1-143 2019-12-10 [1] CRAN (R 3.6.2)
#>  pillar        1.4.3   2019-12-20 [1] CRAN (R 3.6.2)
#>  pkgbuild      1.0.6   2019-10-09 [1] CRAN (R 3.6.0)
#>  pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 3.6.0)
#>  pkgload       1.0.2   2018-10-29 [1] CRAN (R 3.6.1)
#>  prettyunits   1.0.2   2015-07-13 [1] CRAN (R 3.6.1)
#>  processx      3.4.1   2019-07-18 [1] CRAN (R 3.6.1)
#>  ps            1.3.0   2018-12-21 [1] CRAN (R 3.6.1)
#>  purrr       * 0.3.3   2019-10-18 [1] CRAN (R 3.6.1)
#>  R6            2.4.1   2019-11-12 [1] CRAN (R 3.6.2)
#>  Rcpp          1.0.3   2019-11-08 [1] CRAN (R 3.6.2)
#>  readr       * 1.3.1   2018-12-21 [1] CRAN (R 3.6.1)
#>  readxl        1.3.1   2019-03-13 [1] CRAN (R 3.6.1)
#>  remotes       2.1.0   2019-06-24 [1] CRAN (R 3.6.1)
#>  reprex        0.3.0   2019-05-16 [1] CRAN (R 3.6.3)
#>  rlang         0.4.6   2020-05-02 [1] CRAN (R 3.6.3)
#>  rmarkdown     2.0     2019-12-12 [1] CRAN (R 3.6.2)
#>  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 3.6.1)
#>  rvest         0.3.5   2019-11-08 [1] CRAN (R 3.6.3)
#>  scales        1.1.0   2019-11-18 [1] CRAN (R 3.6.2)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.6.1)
#>  stringi       1.4.3   2019-03-12 [1] CRAN (R 3.6.0)
#>  stringr     * 1.4.0   2019-02-10 [1] CRAN (R 3.6.1)
#>  testthat      2.3.1   2019-12-01 [1] CRAN (R 3.6.2)
#>  tibble      * 3.0.1   2020-04-20 [1] CRAN (R 3.6.3)
#>  tidyr       * 1.0.0   2019-09-11 [1] CRAN (R 3.6.1)
#>  tidyselect    1.1.0   2020-05-11 [1] CRAN (R 3.6.3)
#>  tidyverse   * 1.3.0   2019-11-21 [1] CRAN (R 3.6.3)
#>  usethis       1.5.1   2019-07-04 [1] CRAN (R 3.6.1)
#>  utf8          1.1.4   2018-05-24 [1] CRAN (R 3.6.1)
#>  vctrs         0.3.0   2020-05-11 [1] CRAN (R 3.6.3)
#>  withr         2.1.2   2018-03-15 [1] CRAN (R 3.6.1)
#>  xfun          0.11    2019-11-12 [1] CRAN (R 3.6.2)
#>  xml2          1.2.2   2019-08-09 [1] CRAN (R 3.6.1)
#>  yaml          2.2.0   2018-07-25 [1] CRAN (R 3.6.0)
#> 
#> [1] C:/Users/xzhu/Documents/R/win-library/3.6
#> [2] C:/Program Files/R/R-3.6.0/library
Xiurui Zhu
  • 43
  • 6

1 Answers1

0

Yes, you can use map2 :

library(dplyr)
df %>% mutate(data = purrr::map2(name, data, ~{names(.y) <- .x;.y}))

Or Map in base R :

df$data <- Map(function(x, y) {names(y) <- x;y}, df$name, df$data)

If you want to use rowwise a similar approach would be :

df %>% rowwise() %>% mutate(data = {names(data) <- name;list(data)}) 
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Thanks, but I am wondering whether I can use rowwise-mutate instead of `map` or I `have to` use `map` here. – Xiurui Zhu Jun 19 '20 at 00:04
  • Updated the answer to include answer with `rowwise`. – Ronak Shah Jun 19 '20 at 00:08
  • Since I saw that `mutate` on a `rowwise` tibble acted just like `map`, I was thinking of changing my `map`s in my `mutate`s to `rowwise`+`mutate` usage without `map`s, and it looked a little bit tidier. – Xiurui Zhu Jun 19 '20 at 00:11
  • Yes, I think yor answer worked, but the process is actually: (a) when changing the column name of the first element, the column names of ALL elements changed to "a", (b) when changing the column name of the second element, the column names of ALL elements except for the first element changed to "b"; ... You can check this by adding `print(data);` before `names(data)`. So, the `mutate` on a rowwise-tibble does not follow row-wise operation on the variables taking part in the mutation? – Xiurui Zhu Jun 19 '20 at 00:19
  • If I want to change the column name by searching with column name ("value" here) rather than by index (e.g. colnames(data)[1]), what can I do with `rowwise`-`mutate` then? – Xiurui Zhu Jun 19 '20 at 00:21
  • OK, I see. The problem here is that, the changes made to .x (as the variable in `mutate_at`) actually takes effect on the rows after the current row, rather than destroyed when the `~ { }` function finished. If I make changes on a temporary variable set to .x rather than `.x` itself, the problem can be solved, like this: `tmp <- .x; colnames(tmp)[colnames(tmp) %in% "value"] <- name; list(tmp)`. – Xiurui Zhu Jun 19 '20 at 00:39
  • `mutate_at` works on the values of the column and not on column names. I am not sure if using `mutate_at` is correct approach here. I would expect something like this to work but it doesn't `df %>% rowwise() %>% mutate(data = {names(data)[names(data) == 'value'] <- name;list(data)})` – Ronak Shah Jun 19 '20 at 01:39
  • Yes. Previously I expected `mutate_at` would destroy the value changes made to variables inside the function it used, but actually it did not, and even with `rowwise()` applied to the tibble, the changes were subject to the current row and the rows downwards (e.g. the first iteration, it made changes to the elements in rows 1, 2, 3, ...; the second iteration, it did so to the elements in rows 2, 3, ...; etc.) – Xiurui Zhu Jun 19 '20 at 02:18
  • The safest way to do so was to copy the variable's value to a temporary variable and then played with the temporary variable, since the temporary variable will be refreshed when the value of a new element of the variable was passed on to it during a new iteration. – Xiurui Zhu Jun 19 '20 at 02:18
  • And for the function of `mutate_at`, what I wanted to do was to change the tibbles (serving as values) in the `data` column, not the names of `data` column, but rather one of the column names of each of the tibbles (values). I'm not sure if this is correct. – Xiurui Zhu Jun 19 '20 at 02:22
  • What is the problem with `map2` or `Map` approach that I suggest? – Ronak Shah Jun 19 '20 at 02:23
  • There are no problems for those solutions. I'm just trying to understand the process of `mutate_at` when applied to a rowwise tibble. All solutions are okay. Acutally, at the very beginning, I was using `map` functions all the way long in `mutate` functions for list columns, until I got to know `rowwise` function. – Xiurui Zhu Jun 19 '20 at 02:25