使用r中的前n列划分一组n列

knpiaxh1  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(147)

我有这样一个数据框:

df <- data.frame(a = c(1,2,3,4), 
                 b = c(5,6,7,8), 
                 c = c(22,33,44,55), 
                 d = c(7,8,9,10), 
                 e = c(2,3,4,5), 
                 f = c(99,88,66,44))
df
  a b  c  d e  f
1 1 5 22  7 2 99
2 2 6 33  8 3 88
3 3 7 44  9 4 66
4 4 8 55 10 5 44

我希望每2列(或n的倍数)除以前2列(或n列):

df$c <- df$c / df$a
df$d <- df$d / df$b
df$e <- df$e / df$a
df$f <- df$f / df$b
df$a <- df$a / df$a
df$b <- df$b / df$b

导致:

df
  a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000

是否有一种方法可以更简单地和/或使用dplyr来完成此操作?

qgzx9mmu

qgzx9mmu1#

我们可以复制这些列,然后除以base R

n <- 2
df <- df/df[seq_len(n)][rep(seq_len(n), ncol(df)/n)]
  • 输出
> df
  a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000

或者,对于dplyr,使用across在交替列上循环以执行除法

library(dplyr)
df %>%
   mutate(across(seq(1, ncol(.), 2), ~ .x/a),
      across(seq(2, ncol(.), 2), ~ .x/b))
  • 输出
a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000

或者使用具有if/else条件的单个across

df %>%
   mutate(across(everything(),
    ~ if(match(cur_column(), names(df)) %% 2 == 0) .x/b else .x/a))
  • 输出
a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000

或者,另一种方法是将数据split为区块并划分

library(purrr)
library(magrittr)
df %>% 
   split.default(as.integer(gl(ncol(.), n, ncol(.)))) %>% 
   unname %>% 
   map(~ df %>% 
       select(seq_len(n)) %>% 
       divide_by(.x, .)) %>%
   list_cbind()
  • 输出
a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000
enxuqcxy

enxuqcxy2#

@akrun发现了几乎所有的可能性,但我认为这个变异也值得呈现:其思想是将 Dataframe 分为两部分,偶数列索引和奇数列索引分别对每个列索引进行计算,并在最后使用bind_cols在一次运行中绑定它们:

library(dplyr)

df[, c(TRUE,FALSE)] %>% 
  mutate(across(, ~./a)) %>% 
  bind_cols(df[, c(FALSE, TRUE)] %>% 
              mutate(across(, ~./b))
            ) %>% 
  select(order(colnames(.)))
a b        c        d        e         f
1 1 1 22.00000 1.400000 2.000000 19.800000
2 1 1 16.50000 1.333333 1.500000 14.666667
3 1 1 14.66667 1.285714 1.333333  9.428571
4 1 1 13.75000 1.250000 1.250000  5.500000

相关问题