【问题标题】:How to just keep the minimum value in a row across multiple columns and make all other row values 0 in R如何在多列中保持最小值并使所有其他行值在 R 中为 0
【发布时间】:2020-09-14 09:24:10
【问题描述】:

我有一个数据框,其中包含城市中不同地区之间的距离。在根据条件进行分组时,某些位置会因此被其他位置“共享”,从而导致计算过程中的重复。因此,为了纠正重复,我试图计算一行的最小距离,并将该行中的所有其他值设为 0,这样我就可以只将行最小值纳入我的计算中。

Sample data:

> df <- data.frame(name = letters[1:3],
+                  col1 = rnorm(3,10,1),
+                  col2 = rnorm(3,10,1),
+                  col3 = rnorm(3,10,1))
> df
  name      col1      col2     col3
1    a  9.994703 10.882758 9.005535
2    b 11.505343  9.613655 9.589866
3    c 11.713150  9.240391 9.788279
> df$min <- apply(df[,2:4],1,min)
> df
  name      col1      col2     col3      min
1    a  9.994703 10.882758 9.005535 9.005535
2    b 11.505343  9.613655 9.589866 9.589866
3    c 11.713150  9.240391 9.788279 9.240391
> 

现在,我需要将非最小值的值设为 0。 预期输出:

> df
  name      col1      col2     col3      min
1    a       0         0   9.005535 9.005535
2    b       0         0   9.589866 9.589866
3    c       0    9.240391   0      9.240391

谁能告诉我怎么做。

【问题讨论】:

    标签: r dplyr apply


    【解决方案1】:

    我猜你真的不需要min 列。您可以通过将其与行的最小值进行比较,将同一 apply 调用中的值变为 0。

    df[, 2:4] <- t(apply(df[,2:4],1,function(x) x * +(x == min(x))))
    df
    
    #  name     col1 col2     col3
    #1    a 9.439524    0 0.000000
    #2    b 0.000000    0 8.734939
    #3    c 0.000000    0 9.313147
    

    数据

    set.seed(123)
    df <- data.frame(name = letters[1:3],
                     col1 = rnorm(3,10,1),
                     col2 = rnorm(3,10,1),
                     col3 = rnorm(3,10,1))
    df
    #  name      col1     col2      col3
    #1    a  9.439524 10.07051 10.460916
    #2    b  9.769823 10.12929  8.734939
    #3    c 11.558708 11.71506  9.313147
    

    【讨论】:

    • Ronak,您能否解释一下这部分“+(x == min(x))”的作用。我猜“x == min(x)”会检查元素“x”是否在该行中为 min,之后呢?
    • x == min(x) 检查该值是否为最小值。它将返回TRUE 的最小值和FALSE 剩余的值。在此之前使用+ 将它们更改为整数。所以TRUE 变为 1,FALSE 变为 0。
    【解决方案2】:

    dplyrpurrr 的一个解决方案可能是:

    df %>%
     mutate(min_col = pmap(across(starts_with("col")), min),
            across(starts_with("col"), ~ (. == min_col) * .))
    
      name col1 col2      col3  min_col
    1    a    0    0  9.659657 9.659657
    2    b    0    0 10.288515 10.28851
    3    c    0    0  9.303990  9.30399
    

    【讨论】:

    • 好的,我猜 colnames 被硬编码为以 'col' 开头,而我的原始数据框并非如此。此外,函数 'across' 抛出此错误:在 R 中找不到函数“across”
    • 更新到最新版本的dplyr。关于列,您还可以通过索引across(2:4, fun 或作为列名向量across(c("a", "b", "c"), fun) 选择它们。
    • 抛出此错误:df %>% mutate(min_col = pmap(across(starts_with("col")), min) 中的错误:找不到函数 "%>%" > 库(dplyr) 错误: 'dplyr' 在 loadNamespace (j = 1.3.2 另外:警告消息:包 'dplyr' 是在 R 版本 3.6.3 下构建的
    • 您可能缺少一些必需的软件包。试试install.packages("dplyr", dep = TRUE)
    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 2021-09-03
    • 1970-01-01
    • 2023-01-19
    • 2019-08-05
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多