首页 > 解决方案 > R函数没有赋值

问题描述

在此处使用来自 Kaggle 的波士顿住房数据 train.csv 。我尝试编写一个函数,如果该行包含 NA 值或已经为 0,则将 GarageYrBlt 列的值更改为 0,否则为 1。

此列包含建造车库的年份,但缺少值和零。

我对 R 比较陌生,我拼凑了下面的函数来尝试替换本列中的值。

library(tidyverse)
housing_prices <- read_csv('../input/train.csv')


garage <- function(x) {
    for (i in 1:length(x)){
    if (is.na(x[i])) {
       x[i] = 0}
    else if (x[i] > 0) { 
        x[i] = 1} 
    else x[i]=0}
}

garage(housing_prices$GarageYrBlt)

如果我在函数的最后一个花括号之前放置一个 print(x) 语句,我可以看到逻辑工作正常。但是,它不会将值分配回 GarageYrBlt 列。我知道我在这里遗漏了一些简单的东西。

此外,如果有人知道实现此目的的矢量化方式或一般有任何其他提示,他们将不胜感激。

标签: rtidyverse

解决方案


函数返回最后一个值。将xreturn(x)放在函数的末尾,以便将修改x后的内容从函数中返回。

garage <- function(x) {
    for (i in 1:length(x)) {
        if (is.na(x[i])) {
            x[i] = 0}
        else if (x[i] > 0) { 
            x[i] = 1
        } 
        else x[i] = 0
    }
    x
}

然后,如果要分配结果,则需要使用=or分配它<-

housing_prices$GarageYrBlt = garage(housing_prices$GarageYrBlt)

当然,我们可以使用矢量化ifelse而不是iffor 循环:

housing_prices$GarageYrBlt = ifelse(is.na(housing_prices$GarageYrBlt), 0,
     ifelse(housing_prices$GarageYrBlt > 0, 1, 0)) 

既然你放了tidyverse标签,一个更好的方法dplyr是使用case_when

housing_prices %>% 
  mutate(GarageYrBlt = case_when(
    is.na(GarageYrBlt) ~ 0,
    GarageYrBlt > 0 ~ 1,
    TRUE ~ 0
))

或者,coalesce()是一个很好dplyr的填充NA值的实用程序,所以我们可以这样做

housing_prices %>% 
  mutate(GarageYrBlt = ifelse(coalesce(GarageYrBlt, 0) > 0, 1, 0))

或者,更有趣的是,我们可以使用默认转换TRUE为 1 和FALSE0:

housing_prices %>% 
  mutate(GarageYrBlt = as.integer(coalesce(GarageYrBlt, 0) > 0))

推荐阅读