首页 > 解决方案 > 向量化的 Mutate_at 和 ifelse 问题

问题描述

我认为如果我显示会更容易,有什么问题,所以我有这个数字数据

  MoSold YrSold SalePrice OverallQual OverallCond
1      2      3    208500           7           5
2      5      2    181500           6           8
3      9      3    223500           7           5
4      2      1    140000           7           5
5     12      3    250000           8           5
6     10      4    143000           5           5

多亏了 mutate_at 和嵌套的 ifelse,如果条件为真(列均值高于 0.8),我想更改每一行但是当我尝试使用此代码执行此操作时

data %>% 
  mutate_at(vars(MoSold, YrSold, SalePrice, OverallQual, OverallCond), 
            ~(ifelse((mean(., na.rm = T)) > 4, log(.), .))) %>% head()

我得到以下数据,所有列都具有相同的值

     MoSold YrSold SalePrice OverallQual OverallCond
1 0.6931472      3  12.24769     1.94591    1.609438
2 0.6931472      3  12.24769     1.94591    1.609438
3 0.6931472      3  12.24769     1.94591    1.609438
4 0.6931472      3  12.24769     1.94591    1.609438
5 0.6931472      3  12.24769     1.94591    1.609438
6 0.6931472      3  12.24769     1.94591    1.609438

如果条件为真,我想记录每行对应的值,如果条件为假,则记录原始值

我知道一种解决方案是使用 for 循环,但我真的很喜欢 dplyr/tidyverse 的解决方案

提前致谢

我。

标签: rif-statementtidyversedplyr

解决方案


该问题与mean用作testfor相关ifelse,它是单个值,而 'yes'、'no' 参数的长度不同,即导致单个 TRUE/FALSE 的逻辑表达式,这将被复制完整回收“是”、“否”的第一个元素的长度

在这里,我们可以使用if/else代替ifelse

library(dplyr)
data %>%
   mutate_all(~ if(mean(., na.rm = TRUE) > 4) log(.) else .)

dplyr1.0.0 中,一个选项是mutate/across

data %>%
   mutate(across(everything(),
         ~ if(mean(., na.rm = TRUE) > 4) log(.) else .))
#  MoSold YrSold SalePrice OverallQual OverallCond
#1 0.6931472      3  12.24769    1.945910    1.609438
#2 1.6094379      2  12.10901    1.791759    2.079442
#3 2.1972246      3  12.31717    1.945910    1.609438
#4 0.6931472      1  11.84940    1.945910    1.609438
#5 2.4849066      3  12.42922    2.079442    1.609438
#6 2.3025851      4  11.87060    1.609438    1.609438

如果我们想使用ifelse,复制单个逻辑值以使所有 'test'、'yes'、'no' 的长度相同

data %>% 
   mutate_at(vars(MoSold, YrSold, SalePrice, OverallQual, OverallCond), 
             ~(ifelse(rep((mean(., na.rm = T)) > 4, n()), log(.), .)))
#     MoSold YrSold SalePrice OverallQual OverallCond
#1 0.6931472      3  12.24769    1.945910    1.609438
#2 1.6094379      2  12.10901    1.791759    2.079442
#3 2.1972246      3  12.31717    1.945910    1.609438
#4 0.6931472      1  11.84940    1.945910    1.609438
#5 2.4849066      3  12.42922    2.079442    1.609438
#6 2.3025851      4  11.87060    1.609438    1.609438

数据

data <- structure(list(MoSold = c(2L, 5L, 9L, 2L, 12L, 10L), YrSold = c(3L, 
2L, 3L, 1L, 3L, 4L), SalePrice = c(208500L, 181500L, 223500L, 
140000L, 250000L, 143000L), OverallQual = c(7L, 6L, 7L, 7L, 8L, 
5L), OverallCond = c(5L, 8L, 5L, 5L, 5L, 5L)), class = "data.frame",
row.names = c("1", 
"2", "3", "4", "5", "6"))

推荐阅读