在R中按行计算范围

4

我有一个 4x4 的 tibble,我正在练习使用各种 dplyr 函数。

我想计算每一行的范围,并将该行的范围显示为新列中的一个单独数字。

这是我的代码:

my_tibble <- data.frame(col1 = c(1:5), col2 = c(6:10), col3 = c(11:15), col4 = c(16:20))
my_tibble <- as_tibble(my_tibble)

我尝试使用for循环来解决这个问题,但是不理解for循环如何与子集化的tibble数据交互:
for (rows in 1:4)
  my_range <- max(my_tibble[rows, 1:4]) - min(my_tibble[rows, 1:4])

简而言之,我希望以尽可能多的方式在tibble的新列中显示最大-最小值(即范围)。
4个回答

5
在基本的R语言中,您可以在一个apply语句中使用diffrange函数:

my_tibble$rngdiff <- apply(my_tibble, 1, function(x) diff(range(x)))

diff(range(x)) 找到输入的范围并取差值。将索引设置为1apply函数在每一行上执行该函数。输出:

# A tibble: 5 × 5
   col1  col2  col3  col4  rngdiff
  <int> <int> <int> <int>    <int>
1     1     6    11    16       15
2     2     7    12    17       15
3     3     8    13    18       15
4     4     9    14    19       15
5     5    10    15    20       15

你提出的for循环有两个主要问题:(1) 你没有对my_range进行索引,所以每次迭代都会被覆盖;(2) 你的rows索引没有涵盖所有行的总数(共有5行)。一个正确的for循环语句可能是:

my_tibble$diffloop <- NA
for(rows in seq_len(nrow(my_tibble))){
  my_tibble$diffloop[rows] <- max(my_tibble[rows, 1:4]) - min(my_tibble[rows, 1:4])
  # or
  # my_tibble$diffloop[rows] <- diff(range(my_tibble[rows, 1:4]))
}

(虽然出于记录的目的,我认为你不应该在这里使用 for 循环)


4

使用 rowwise 可以让你直接使用 minmax

library(tidyverse)

my_tibble %>%
  rowwise() %>%
  mutate(range = max(c_across(col1:col4)) - min(c_across(col1:col4)))

# A tibble: 5 × 5
# Rowwise: 
   col1  col2  col3  col4 range
  <int> <int> <int> <int> <int>
1     1     6    11    16    15
2     2     7    12    17    15
3     3     8    13    18    15
4     4     9    14    19    15
5     5    10    15    20    15

1

pmax/pmin 的另一个选项

my_tibble$range <- do.call(`-`, lapply(c(pmax, pmin), \(f) do.call(f, my_tibble)))

提供

> my_tibble
# A tibble: 5 × 5
   col1  col2  col3  col4 range
  <int> <int> <int> <int> <int>
1     1     6    11    16    15
2     2     7    12    17    15
3     3     8    13    18    15
4     4     9    14    19    15
5     5    10    15    20    15

0

使用 pmax/pmin

library(dplyr)
 my_tibble %>% 
  mutate(range = do.call(pmax, pick(everything())) - 
   do.call(pmin, pick(everything())))

-输出

# A tibble: 5 × 5
   col1  col2  col3  col4 range
  <int> <int> <int> <int> <int>
1     1     6    11    16    15
2     2     7    12    17    15
3     3     8    13    18    15
4     4     9    14    19    15
5     5    10    15    20    15

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接