1

I want to do row wise calculation with dplyr package of R.The result of the calculation is a series. Then I want to replace the entire row with the calculated series. Here is the code:

df <- tibble(id = 1:6, w = 10:15, x = 20:25, y = 30:35, z = 40:45)

I want to run isoreg which the result is a series then replace it with what is under w:z columns:

df %>% rowwise %>%
  mutate(across(c_across(w:z), ~ isoreg(as.numeric(c_across(w:z)))$yf))

It seems this method is just for replacing one element, not the entire row. The isoreg is just a sample function, we could use other functions that return a series not a single value as the output.

UseR10085
  • 7,120
  • 3
  • 24
  • 54

2 Answers2

1

You don't need to use across as well c_across. For rowwise operations use only c_across. Also c_across expects a single summary value as output so you can't replace all the rows in one go. A hack is to capture all the values in a list and use unnest_wider to get those values as separate columns.

library(dplyr)
df %>% 
  rowwise() %>%
  mutate(output = list(isoreg(c_across(w:z))$yf)) %>%
  tidyr::unnest_wider(output)


#     id     w     x     y     z  ...1  ...2  ...3  ...4
#  <int> <int> <int> <int> <int> <dbl> <dbl> <dbl> <dbl>
#1     1    10    20    30    40    10    20    30    40
#2     2    11    21    31    41    11    21    31    41
#3     3    12    22    32    42    12    22    32    42
#4     4    13    23    33    43    13    23    33    43
#5     5    14    24    34    44    14    24    34    44
#6     6    15    25    35    45    15    25    35    45

Since the output of isoreg is not named unnest_wider gives names as ..1, ..2 etc. You can rename them if needed and remove the columns which you don't need.


Base R option is to use apply :

df[-1] <- t(apply(df[-1], 1, function(x) isoreg(x)$yf))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • I was struggling with a similar problem and could not get `mutate` to replace the existing data set in place just like `pmap_dfc` for example and saw your post and realized we should just create as many columns as the original one and `rename` them for example. Is there actually any way we could replace them in place without using `purrr`? – Anoushiravan R Jun 18 '21 at 23:57
  • 1
    Why not use the same approach as in this answer? Store the columns in a list and then use `unnest_wider` ? – Ronak Shah Jun 19 '21 at 01:14
  • I used it here https://stackoverflow.com/questions/68042067/r-dplyr-replace-missing-column-data-with-first-non-missing-value/68042488#68042488 It's totally fine and sensible. I was just wondering there might be any direct way. Thank you very much for the guidance dear Ronak. – Anoushiravan R Jun 19 '21 at 08:43
1

We could use pmap with unnest_wider

library(dplyr)
library(tidyr)
library(purrr)
df %>% 
   mutate(new = pmap(select(., w:z), ~ isoreg(c(...))$yf)) %>% 
   unnest_wider(c(new))
# A tibble: 6 x 9
#     id     w     x     y     z  ...1  ...2  ...3  ...4
#  <int> <int> <int> <int> <int> <dbl> <dbl> <dbl> <dbl>
#1     1    10    20    30    40    10    20    30    40
#2     2    11    21    31    41    11    21    31    41
#3     3    12    22    32    42    12    22    32    42
#4     4    13    23    33    43    13    23    33    43
#5     5    14    24    34    44    14    24    34    44
#6     6    15    25    35    45    15    25    35    45
akrun
  • 874,273
  • 37
  • 540
  • 662