Home > front end >  I want to add two related columns and reduce the data matrix by half
I want to add two related columns and reduce the data matrix by half

Time:09-30

DF <- data.frame(hour1=c(3,2,1), 
                 minutes1=c(0.083,0.17,0.25),
                 hour2=c(4,3,2), 
                 minutes2=c(0.09,0.18,0.35))

DF
#>   hour1 minutes1 hour2 minutes2
#> 1     3    0.083     4     0.09
#> 2     2    0.170     3     0.18
#> 3     1    0.250     2     0.35

What I am looking for must be more efficient because I have to add 58 pairs of columns....

DF_new<-DF%>%summarise(t1=hour1 minutes1,
                    t2=hour2 minutes2)
DF_new
#>      t1   t2
#> 1 3.083 4.09
#> 2 2.170 3.18
#> 3 1.250 2.35

CodePudding user response:

Does this work:

library(dplyr)
library(purrr)

hour <- names(DF)[grep('hour', names(DF))]
min <- names(DF)[grep('min', names(DF))]

map2_dfc(hour, min, ~{
  col <- paste0('t', gsub('([a-z] )(\\d$)','\\2', .x))
  DF %>% rowwise() %>% transmute(!!col := .data[[.x]]   .data[[.y]])
})
# A tibble: 3 × 4
# Rowwise: 
     t1    t2    t3    t4
  <dbl> <dbl> <dbl> <dbl>
1  3.08  4.09  6.1   4.09
2  2.17  3.18  2.17  3.28
3  1.25  2.35  1.25  6.35

CodePudding user response:

You could pivot to long format, add the columns, then pivot back to wide. This works as expected with your example, but will work with an arbitrary number of columns

library(tidyverse)

DF %>%
  pivot_longer(everything(), names_pattern = '(\\D )(\\d )', 
               names_to = c(".value", "t")) %>%
  mutate(time = hour   minutes, t = paste0('t', t)) %>%
  select(t, time) %>%
  pivot_wider(names_from = t, values_from = time, values_fn = list) %>%
  unnest(everything())
#> # A tibble: 3 x 2
#>      t1    t2
#>   <dbl> <dbl>
#> 1  3.08  4.09
#> 2  2.17  3.18
#> 3  1.25  2.35

A simpler approach, provided you only have the hour and minutes columns in DF would be to select the hours columns and minutes columns then add them:

library(tidyverse)

DF %>% 
  transmute(across(contains('min'), ~.x)   across(contains('hour'), ~.x)) %>%
  rename_with(~sub('minutes', 't', .x))
#> # A tibble: 3 x 2
#>      t1    t2
#>   <dbl> <dbl>
#> 1  3.08  4.09
#> 2  2.17  3.18
#> 3  1.25  2.35

Created on 2022-09-29 with reprex v2.0.2

  •  Tags:  
  • r
  • Related