首页 > 解决方案 > 无法使用 R 执行迭代

问题描述

我一直在练习泰坦尼克号数据集并取得了稳步进展。但是,当我尝试根据某些条件用中位年龄替换缺失的“年龄”变量时,我遇到了困难。这是数据集:

| Pclass | Name      |   Sex  | Age |
|:------:|:---------:|:------:|:---:|
|    2   |  officer  |  male  |  NA |
|    3   |  mr       |  male  |  27 |
|    3   |  miss     | female |  NA |

现在,我想用我计算的中位年龄替换 NA,并保留已经存在的年龄。为此,我使用以下代码进行迭代:

age_fill <- function(x){ 

    for (i in length(x$Age)) {

      if (!is.na(x$Age[i])) {
          return(x$Age[i])

      }

      else if(is.na(x$Age[i])){


        if (x$Sex[i] == "female" && x$Pclass[i] == "3" && x$Name[i] == "miss"){
          x$Age[i] = 18
        }

        if (x$Sex[i] == "male" && x$Pclass[i] == "2" && x$Name[i] == "mr"){
          x$Age[i] = 29
        }

        if (x$Sex[i] == "male" && x$Pclass[i] == "3" && x$Name[i] == "officer"){
          x$Age[i] = 25
        }

     }

  }
  return(x)
}

当我将代码作为函数循环运行时,这里的问题没有任何变化。但是,如果我通过输入行的数字来单独运行它,它会很好地返回结果。

有人可以告诉我我做错了什么吗?

标签: r

解决方案


你的问题

关于您的功能,有几个问题:


age_fill <- function(x){ 

    for (i in length(x$Age)) {

      if (!is.na(x$Age[i])) {
          return(x$Age[i])

      }
# some more code
}
  1. 您的for-loop 只循环一个元素:length(x$Age)返回一个值。我猜你把它误认为1:length(x$Age).

  2. 如果您的函数遇到非NA值,return(x$Age[i])将中断/停止您的函数并返回一个值。我不认为那是你想要的。在非NA值的情况下,您希望您的函数不更改任何内容。因此,您应该删除这整个部分:

      if (!is.na(x$Age[i])) {
          return(x$Age[i])

      }

      else 

你的情况

if(is.na(x$Age[i])){
# enter code here
}

就足够了。

替代方法

这是一个使用dplyr. 这不是您问题的直接答案,但我想向您展示解决问题的另一种方法。给定一个数据集

> df
# A tibble: 6 x 4
  Pclass Name    Sex      Age
   <dbl> <chr>   <chr>  <dbl>
1      2 officer male      NA
2      3 mr      male      27
3      3 miss    female    NA
4      3 mr      male      NA
5      2 mr      male      NA
6      3 officer male      NA

我用包创建的readr

df <- read_table2("Pclass  Name        Sex   Age
    2     officer    male    NA 
    3     mr         male    27 
    3     miss       female   NA 
    3     mr         male     NA
    2     mr         male     NA
    3     officer    male     NA")

现在我们mutate结合使用case_when

df %>%
  mutate(Age = case_when(!is.na(Age) ~ Age,
                         Sex == "male"   & Pclass == "3" & Name == "officer" ~ 25,
                         Sex == "male"   & Pclass == "2" & Name == "mr"      ~ 29,
                         Sex == "female" & Pclass == "3" & Name == "miss"    ~ 18
                        ))

产生

# A tibble: 6 x 4
  Pclass Name    Sex      Age
   <dbl> <chr>   <chr>  <dbl>
1      2 officer male      NA
2      3 mr      male      27
3      3 miss    female    18
4      3 mr      male      NA
5      2 mr      male      29
6      3 officer male      25

使用这种方法,您不需要函数或任何类型的循环,并且您的条件安排得很清楚。根据经验:尽量避免循环。通常有更复杂的方法来执行没有循环的任务。R 在针对性能优化的函数内部使用“隐藏循环”。然而,有些任务非常适合循环。所以决定取决于实际任务。


推荐阅读