按行查找未知列数的最小值和最大值

4

对于一个数据框,我需要找到每一行从第二列开始的未知列数中的最小值和最大值。以下是一个示例:

library(tidyverse)

# test data
(test_data <- tibble(id = c(1:9), 
                     x = runif(9), 
                     x2 = runif(9),
                     x3 = runif(9)))
samples = 100    

# This example, which specifies the column names, correctly finds the min and max values by row
(test_1 <- test_data %>% 
  rowwise() %>%
  mutate(min_val = min(x, x2, x3), max_val = max(x, x2, x3)))

# This example does not
(test_2 <- test_data %>% 
    rowwise() %>%
    mutate(min_val = min(x:x3), max_val = max(x:x3)))

我实际想要做的是类似于

mutate(min_val = min([,2:samples+1]), max_val = max([,2:samples+1])))

因为我希望保留 id 列(以便与另一个数据框连接),并且指定列位置似乎是一种明显的方法,因为我不关心列名,而且样本可能很大。谢谢! 编辑后的示例 这个(如建议的)
test_data %>%
  nest(-id) %>%                         # nest rest of columns apart from id
  mutate(min_val = map(data, min),      # get min and max
         max_val = map(data, max)) %>%
  unnest()   

这段代码可以在原始测试数据上运行。但是,在现实世界的数据中,会出现id重复的情况,例如:

(test_data <- tibble(id = c(1:9, 1:9), 
                     x = runif(18), 
                     x2 = runif(18),
                     x3 = runif(18)))

这导致出现“错误:所有嵌套列必须具有相同数量的元素。”。
2个回答

3

一个可能的 tidyverse 解决方案是将除了 id 以外的任何列都进行 nest,然后使用 map 获取 minmax。您不需要指定任何列名:

library(tidyverse)

# test data
(test_data <- tibble(id = c(1:9), 
                     x = runif(9), 
                     x2 = runif(9),
                     x3 = runif(9)))
samples = 100    

test_data %>%
  nest(-id) %>%                         # nest rest of columns apart from id
  mutate(min_val = map(data, min),      # get min and max
         max_val = map(data, max)) %>%
  unnest()                              # unnest columns

# # A tibble: 9 x 6
#      id min_val max_val      x     x2    x3
#   <int>   <dbl>   <dbl>  <dbl>  <dbl> <dbl>
# 1     1  0.0217   0.239 0.130  0.0217 0.239
# 2     2  0.125    0.814 0.625  0.814  0.125
# 3     3  0.281    0.770 0.331  0.770  0.281
# 4     4  0.123    0.868 0.123  0.644  0.868
# 5     5  0.149    0.340 0.149  0.340  0.337
# 6     6  0.496    0.865 0.596  0.865  0.496
# 7     7  0.0766   0.984 0.0766 0.656  0.984
# 8     8  0.272    0.926 0.702  0.926  0.272
# 9     9  0.433    0.912 0.912  0.433  0.590

在有多个ID的情况下,您可以使用以下方法:
test_data %>%
  mutate(row_id = row_number()) %>%     # create a row identifier
  nest(-id, -row_id) %>%                # nest rest of columns apart from id and row id
  mutate(min_val = map(data, min),      # get min and max
         max_val = map(data, max)) %>%
  unnest()                              # unnest columns

1
请注意,您无需调用 group_by()。只需使用 nest(-id) 即可。 - j3ypi
1
谢谢。我习惯于使用group_bynest,但从现在开始会改变这种做法 :) - AntoniosK
谢谢你不仅回答了我的问题,还向我展示了如何在这种情况下使用map(我一直在尝试使用它来获取逐行的最小值和最大值,感觉这将是更好的方法,但没有成功)。这个例子在测试数据集上完美地工作。然而,在我的真实数据集上,我收到“错误:所有嵌套列必须具有相同数量的元素”。这似乎是因为id列具有重复的id值(我已经适当地编辑了原始问题)。谢谢。 - Martino
1
你可以通过 df <- tibble::rowid_to_column(df, "id_uni") 为所有行分配唯一的ID。 - tmfmnk
我已经更新了我的答案。我正在使用 row_number 创建唯一的 ID,但是 rowid_to_column 也非常好。 - AntoniosK

0

这里有一个使用 pmin/pmax 的选项

library(tidyverse)
test_data %>% 
     mutate(min_val = pmin(!!! rlang::syms(names(.)[-1])),
            max_val = pmax(!!! rlang::syms(names(.)[-1])))
# A tibble: 9 x 6
#     id     x     x2     x3 min_val max_val
#  <int> <dbl>  <dbl>  <dbl>   <dbl>   <dbl>
#1     1 0.293 0.255  0.501   0.255    0.501
#2     2 0.225 0.605  0.139   0.139    0.605
#3     3 0.704 0.371  0.0939  0.0939   0.704
#4     4 0.519 0.672  0.552   0.519    0.672
#5     5 0.663 0.673  0.725   0.663    0.725
#6     6 0.920 0.320  0.138   0.138    0.920
#7     7 0.280 0.904  0.223   0.223    0.904
#8     8 0.764 0.198  0.688   0.198    0.764
#9     9 0.802 0.0442 0.0765  0.0442   0.802

数据

set.seed(24)
test_data <- tibble(id = c(1:9), 
                    x = runif(9), 
                    x2 = runif(9),
                    x3 = runif(9))

谢谢:这个方法很好用。它也适用于id = c(1:9, 1_9),即具有重复变量的id,这正是我需要的!它还可以处理我的真实数据(>100,000行)。然而,我承认我不理解语法“min_val = pmin(!!! rlang::syms(names(.)[-1]))”! - Martino
@Martino names(.)[-1] 返回数据集除第一列名称外的列名字符串。它被转换为 symbol 并使用 syms 进行评估 (!!!),以获取对于行最小值或最大值应用 pminpmax 的那些列的值。 - akrun
1
谢谢您的解释(我至少部分理解了!)- 我会进一步学习这个。 - Martino

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