【问题标题】:Loop with conditions in R programmingR编程中的条件循环
【发布时间】:2014-11-19 18:14:15
【问题描述】:

我想比较前一行值是否与当前行值相同(对于超过 1 个变量并且还使用值列表)。在这种情况下,我该如何执行编写代码。我看过'apply'函数可以使用。

我在发布这个问题之前在这里搜索了这个主题,发现有点相似,但找不到确切的问题。我对 R 很陌生。

这是我的示例表:(需要根据条件进行标记)

Ticket No   V1  V2  Flag
Tkt10256    1   X   0
Tkt10257    1   aa  0
Tkt10257    2   bb  1
Tkt10257    3   x   0
Tkt10260    1   cc  0
Tkt10260    2   aa  1
Tkt10262    3   bb  0

我必须根据以下条件标记(如果所有条件都满足则标记为1)

  1. 变量 2 应该是以下 4 个名称之一(aa、bb、cc、dd)
  2. 变量 1 应该与上一行不同
  3. 票号必须与上一行相同

提前感谢您的帮助!

【问题讨论】:

  • 第 3 行和第 4 行的 V1 不同,但您已将其标记为这样。在第 4 行,您在 V2 中有 x,并且您还标记了它。根据您的条件,这些不应为 1。请更正此
  • 我很抱歉理查德的混乱。条件 2 是 v1 应该与上一行不同。

标签: r loops conditional-statements apply


【解决方案1】:

一种没有循环的方法:

indx1 <- with(df, V2 %in% paste0(letters[1:4], letters[1:4]) )
indx2 <- with(df, c(TRUE,V1[-1]!=V1[-length(V1)]))
indx3 <- with(df, c(FALSE,Ticket.No[-1]==Ticket.No[-nrow(df)]))

df$Flag <- (indx1 & indx2 & indx3)+0
df$Flag
#[1] 0 0 1 0 0 1 0

数据

df <- structure(list(Ticket.No = c("Tkt10256", "Tkt10257", "Tkt10257", 
"Tkt10257", "Tkt10260", "Tkt10260", "Tkt10262"), V1 = c(1L, 1L, 
2L, 3L, 1L, 2L, 3L), V2 = c("X", "aa", "bb", "x", "cc", "aa", 
"bb"), Flag = c(0L, 0L, 1L, 1L, 0L, 1L, 0L)), .Names = c("Ticket.No", 
"V1", "V2", "Flag"), class = "data.frame", row.names = c(NA, 
-7L))

【讨论】:

  • 不错。我正在考虑使用 within 和内部的 ifelse
  • @Richard Scriven 谢谢。是的,这是一个选项
  • 运行良好 Akrun,非常感谢!我也在尝试使用循环或应用函数,因为这对我来说是一个很好的学习。
  • @Mathan 对于更大的数据集,循环可能会很慢。我会使用矢量化选项。我猜 rnso 已经给了你一个使用 for 循环的选项
【解决方案2】:

还有一个:

在您的较大数据上进行检查。我不确定duplicated 是否适合在那里使用。如果TicketNo 列中的数字在增加(即 TktXXXXX 中的 X),那么它应该可以正常工作。

> dat2 <- dat[dat$V2 %in% c("aa", "bb", "cc", "dd"),]
> rn <- rownames(dat2)[duplicated(dat2[[1]]) & !c(FALSE, diff(dat2[[2]]) == 0)]
> dat$Flag <- (rownames(dat) %in% rn)+0
> dat
#   TicketNo V1 V2 Flag
# 1 Tkt10256  1  X    0
# 2 Tkt10257  1 aa    0
# 3 Tkt10257  2 bb    1
# 4 Tkt10257  3  x    0
# 5 Tkt10260  1 cc    0
# 6 Tkt10260  2 aa    1
# 7 Tkt10262  3 bb    0

【讨论】:

    【解决方案3】:

    @Akrun 答案的变体:

    with(df, 
      V2 %in% c("aa","bb","cc","dd") &  
      c(FALSE,diff(V1) != 0) &
      c(FALSE,head(Ticket.No, -1)) == Ticket.No
    ) + 0
    
    #[1] 0 0 1 0 0 1 0
    

    【讨论】:

      【解决方案4】:

      试试:

      for(i in 2:nrow(ddf)){
         ddf$Flag[i] = ifelse(  ddf$V2[i] %in% c('aa', 'bb', 'cc', 'dd') 
                 && ddf$V1[i] != ddf$V1[(i-1)] 
                 &&  ddf$TicketNo[i] == ddf$TicketNo[(i-1)]
               ,1,0)
       }
      ddf
        TicketNo V1 V2 Flag
      1 Tkt10256  1  X    0
      2 Tkt10257  1 aa    0
      3 Tkt10257  2 bb    1
      4 Tkt10257  3  x    0
      5 Tkt10260  1 cc    0
      6 Tkt10260  2 aa    1
      7 Tkt10262  3 bb    0
      

      【讨论】:

        猜你喜欢
        • 2019-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-19
        • 1970-01-01
        • 2021-05-06
        相关资源
        最近更新 更多