【问题标题】:How to create a new column in data frame with for loop and if statements如何使用 for 循环和 if 语句在数据框中创建新列
【发布时间】:2014-12-10 18:01:48
【问题描述】:

我有一个包含 102 行的数据框,我需要开发一个带有 if 语句的 for 循环,以根据其他列(Sp、Su、Fa、Wi)填充一个新列“Season”。我有一个“1”填充样本发生的季节(见下文)。

Sp  Su  Fa  Wi
1   0   0   0
0   0   0   1

我试着只做夏天,在一个循环中,但我得到了大量的错误。我似乎无法掌握 For 和 if 循环。任何帮助将不胜感激。

for(i in 1:102) {  if(myData$Su==1) myData$Season=Summer}

错误:

In if (myData$Su == 1) myData$Season = Summer :
  the condition has length > 1 and only the first element will be used

【问题讨论】:

    标签: r if-statement for-loop


    【解决方案1】:

    尝试确定哪一列有 1,然后使用此索引从 char 向量中返回所需的季节名称:

    data <- c("Sp  Su  Fa  Wi
               1   0   0   0
               0   0   0   1")
    data <- read.table(text=data,header=TRUE)
    
    data$Season <- c("Spring","Summer","Fall","Winter")[which(data==1,arr.ind=TRUE)[,"col"]]
    

    结果:

      Sp Su Fa Wi Season
    1  1  0  0  0 Spring
    2  0  0  0  1 Winter
    

    【讨论】:

    • 我喜欢使用 which 的解决方案! :)
    • 非常感谢。这很有帮助。
    • 不客气,请注意,如果有 NA,这将不起作用,因为which 函数将忽略它们,并且您的行数将少于 data.frame。为避免这种情况,请使用@Andrie answer的应用版本
    【解决方案2】:

    由于 R 是一种基于向量的语言,在这种情况下您不需要 for 循环。

    dat <- data.frame(
      Sp = c(1, 0),
      Su = c(0, 0),
      Fa = c(0, 0),
      Wi = c(0, 1)
    )
    

    一种天真的、蛮力的方法是使用嵌套的ifelse() 函数:

    dat$Season <- with(dat, 
                       ifelse(Sp == 1, "Spring", 
                              ifelse(Su == 1, "Summer", 
                                     ifelse(Fa == 1, "Fall", 
                                            "Winter"))))
    dat
    
      Sp Su Fa Wi Season
    1  1  0  0  0 Spring
    2  0  0  0  1 Winter
    

    但是 R 这样做的方式是考虑数据的结构,然后使用索引,例如:

    dat$season <- apply(dat, 1, function(x) c("Sp", "Su", "Fa", "Wi")[x==1])
    
      Sp Su Fa Wi season
    1  1  0  0  0     Sp
    2  0  0  0  1     Wi
    

    【讨论】:

    • 您好,非常感谢。第一种方法效果很好。第二种方式我得到一列“NA”,但我将继续提出第二种方式,因为它看起来更简洁。
    【解决方案3】:
    ifelse(myData$Su==1, myData$Season=="Summer",myData$Season=="Not Summer")
    

    或更复杂的“否”语句(例如嵌套 ifelse - 如果 Wi ==1,设置为 Winter 等)

    【讨论】:

      【解决方案4】:

      如果你真的想使用循环,你应该这样做:

      # recreating an example similar to your data
      myData <- read.csv(text= 
      "Sp,Su,Fa,Wi
      1,0,0,0
      0,1,0,0
      0,0,1,0
      1,0,0,0
      0,0,0,1")
      
      # before the loop, add a new "Season" column to myData filled with NAs
      myData$Season <- NA
      
      # don't use 102 but nrow(myData) so
      # in case myData changes you don't have to modify the code
      for(i in 1:nrow(myData)){
      
        # here you are working row-by-row
        # so note the [i] indexing below
      
        if(myData$Sp[i] == 1){
          myData$Season[i] = "Spring"
        }else if(myData$Su[i] == 1){
          myData$Season[i] = "Summer"
        }else if(myData$Fa[i] == 1){
          myData$Season[i] = "Fall"
        }else if(myData$Wi[i] == 1){
          myData$Season[i] = "Winter"
        }
      }
      

      但实际上(如其他答案所示)有更有效和更快的方法。

      【讨论】:

      • 非常感谢!所有回复都有帮助
      【解决方案5】:

      您也可以使用(@Emer 方法的一种变体)

       transform(dat, Season=c('Spring', 'Summer', 'Fall',
                   'Winter')[as.matrix(seq_len(ncol(dat))*dat)])
       #  Sp Su Fa Wi Season
       #1  1  0  0  0 Spring
       #2  0  0  0  1 Winter
      

      数据

       dat <- structure(list(Sp = c(1, 0), Su = c(0, 0), Fa = c(0, 0), Wi = c(0, 
       1)), .Names = c("Sp", "Su", "Fa", "Wi"), row.names = c(NA, -2L
       ), class = "data.frame")
      

      【讨论】:

        猜你喜欢
        • 2013-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-06
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        相关资源
        最近更新 更多