代码之家  ›  专栏  ›  技术社区  ›  msh855

回路中的多个不同条件和if状态

  •  1
  • msh855  · 技术社区  · 7 年前

    我想从中分配不同的字母 A:U 根据依赖于不同列(取数字)的某些条件,创建一个新的列向量 1:99 .

    我提出了以下解决方案,但我想更有效地编写它。

    for (i in 1:99){
    
      if (i %in% 1:3 == T  ){
        id<-which(H07_NACE$NACE2.Code==i)
        H07_NACE$NACE2.Sectors[id]<-"A"
      }
    
    
       .............         
    
        if (i %in% 45:60 == T  ){
          id<-which(H07_NACE$NACE2.Code==i)
          H07_NACE$NACE2.Sectors[id]<-"D"
        }
          .....................
    
    
         if (i == 99  ){
    id<-which(H07_NACE$NACE2.Code==i)
    H07_NACE$NACE2.Sectors[id]<-"U"
      }
    
    }
    

    在前面的代码中,我跳过了其他几行基本上做相同事情的代码。注意,在我创建的这个循环中,条件一直在变化,并且有两个条件 类型 . 一个是类型示例 i %in% 45:60 == T 另一个类型为“i==99”

    我的原始代码有多个这样的 国际单项体育联合会 在这个循环中,如果有人能帮我写得更高效或简洁,我将不胜感激。

    3 回复  |  直到 7 年前
        1
  •  4
  •   Uwe    7 年前

    用户已请求映射中给定的数字 H07_NACE$NACE2.Code 不折不扣地 "A" "U" 根据给定的规则,他硬编码了一些 if 条款。

    一种更灵活的方法(代码也不那么繁琐)是使用 查阅表格 (或 约束向量 正如约瑟夫·伍德所说 in his answer ).

    具有 data.table ,我们可以使用 滚动连接 或者 非等更新连接 进行映射。

    要映射的样本数据

    set.seed(1)
    H07_NACE <- data.frame(NACE2.Code = sample(99, 10, replace = TRUE))
    

    滚动连接

    对于滚动连接,我们通过平铺数字范围来指定映射规则 1:99 连续并给出每个图块的起始编号。

    library(data.table)
    # set up lookup table
    lookup <- data.table(Code = c(1, 4, 21, 45, 61:75, 98, 99),
                         Sector = LETTERS[1:21])
    lookup
    
        Code Sector
     1:    1      A
     2:    4      B
     3:   21      C
     4:   45      D
     5:   61      E
     6:   62      F
     7:   63      G
     8:   64      H
     9:   65      I
    10:   66      J
    11:   67      K
    12:   68      L
    13:   69      M
    14:   70      N
    15:   71      O
    16:   72      P
    17:   73      Q
    18:   74      R
    19:   75      S
    20:   98      T
    21:   99      U
        Code Sector
    
    # map Code to Sector 
    lookup[setDT(H07_NACE), on = .(Code = NACE2.Code), roll = TRUE]
    
        Code Sector
     1:   27      C
     2:   37      C
     3:   57      D
     4:   90      S
     5:   20      B
     6:   89      S
     7:   94      S
     8:   66      J
     9:   63      G
    10:    7      B
    

    如果 H07_NACE 要更新,我们可以通过

    setDT(H07_NACE)[, NACE2.Sector := lookup[H07_NACE, on = .(Code = NACE2.Code), 
      roll = TRUE, Sector]][]
    
        NACE2.Code NACE2.Sector
     1:         27            C
     2:         37            C
     3:         57            D
     4:         90            S
     5:         20            B
     6:         89            S
     7:         94            S
     8:         66            J
     9:         63            G
    10:          7            B
    

    非等更新连接

    对于非等更新连接,我们通过给出上下限来指定映射规则。这可以从 lookup 通过

    lookup2 <- lookup[, .(Sector, lower = Code, 
                          upper = shift(Code - 1L, type = "lead", fill = max(Code)))]
    lookup2
    
        Sector lower upper
     1:      A     1     3
     2:      B     4    20
     3:      C    21    44
     4:      D    45    60
     5:      E    61    61
     6:      F    62    62
     7:      G    63    63
     8:      H    64    64
     9:      I    65    65
    10:      J    66    66
    11:      K    67    67
    12:      L    68    68
    13:      M    69    69
    14:      N    70    70
    15:      O    71    71
    16:      P    72    72
    17:      Q    73    73
    18:      R    74    74
    19:      S    75    97
    20:      T    98    98
    21:      U    99    99
        Sector lower upper
    

    新列由创建

    setDT(H07_NACE)[lookup2, on = .(NACE2.Code >= lower, NACE2.Code <= upper), 
                    NACE2.Sector := Sector][]
    
    NACE2。代码NACE2。部门
    1: 27摄氏度
    2: 37摄氏度
    3: 57天
    4: 90秒
    5: 20 B
    6: 89秒
    7: 94秒
    8: 66 J
    9: 63克
    10: 7 B
    
        2
  •  3
  •   Joseph Wood    7 年前

    这里有一个快速而肮脏的解决方案,应该可以完成这项工作(我相信有更高效/优雅的方法来完成这项工作)。我们可以设置一个约束向量,并从那里使用索引来生成所需的结果。

    ## Here is some random data that resembles the OP's
    set.seed(3)
    H07_NACE <- data.frame(NACE2.Code = sample(99, replace = TRUE))
    
    ## "T" is the 20th element... we need to gurantee
    ## that the number corresponding to "U" 
    ## corresponds to max(NACE2.Code)
    maxCode <- max(H07_NACE$NACE2.Code)
    constraintVec <- sort(sample(maxCode - 1, 20))
    constraintVec <- c(constraintVec, maxCode)
    
    H07_NACE$NACE2.Sector <- LETTERS[vapply(H07_NACE$NACE2.Code, function(x) {
                                                which(constraintVec >= x)[1]
                                        }, 1L)]
    
    ## Add optional check column to ensure we are mapping the 
    ## Code to the correct Sector
    H07_NACE$NACE2.Check <- constraintVec[vapply(H07_NACE$NACE2.Code, function(x) {
        which(constraintVec >= x)[1]
    }, 1L)]
    
    head(H07_NACE)
      NACE2.Code NACE2.Sector NACE2.Check
    1         17            E          18
    2         80            R          85
    3         39            K          54
    4         33            J          37
    5         60            N          66
    6         60            N          66
    

    更新由@Frank提供

    正如所怀疑的那样,假设上述逻辑正确,有一个更简单的解决方案。我们使用 findInterval 并设置参数 rightmost.closed left.open TRUE (我们还必须添加 1L 到结果向量):

    H07_NACE$NACE2.Sector2 <- LETTERS[findInterval(H07_NACE$NACE2.Code, constraintVec,
                                        rightmost.closed = TRUE, , left.open = TRUE) + 1L]
    
    head(H07_NACE)
      NACE2.Code NACE2.Sector NACE2.Check NACE2.Sector2
    1         17            E          18             E
    2         80            R          85             R
    3         39            K          54             K
    4         33            J          37             J
    5         60            N          66             N
    6         60            N          66             N
    
    identical(H07_NACE$NACE2.Sector, H07_NACE$NACE2.Sector2)
    [1] TRUE
    
        3
  •  1
  •   B Williams    7 年前

    这里有两个 tidyverse 例如,虽然我不完全确定原始海报真正想要什么。

    library(tidyverse)
    
    data.frame(NACE2.Code = sample(99, replace = TRUE)) %>% 
      mutate(Sectors = ifelse(NACE2.Code %in% 1:3, "A", 
                              ifelse(NACE2.Code %in% 45:60, "D",
                                     ifelse(NACE2.Code ==99, "U", NA))))
    
    data.frame(NACE2.Code = sample(99, replace = TRUE)) %>% 
      mutate(Sectors = case_when(NACE2.Code %in% 1:3 ~ "A", 
                                 NACE2.Code %in% 45:60 ~ "D",
                                 NACE2.Code ==99 ~ "U")) %>% 
      drop_na