【问题标题】:Add column to Data Frame based on values of other columns根据其他列的值将列添加到数据框中
【发布时间】:2014-09-26 19:42:54
【问题描述】:

我的数据框 DF 看起来像:

ID    Name1    Name2    Group    
1234  A1       x
1234  A4       w
1234  A3       q
1234  A        A
1234  A2       z
5678  B3       s
5678  B        B
...

我需要为Group 添加一个列,即Name1,每个IDID 所在行中的ID 匹配。

因此逻辑是检查 Name1 == Name2,记住该 Row 的 ID 和 Name1 值,然后对于具有该 ID 的每一行,将 Name1 值放入 Group 列的每一行。

结果应该是这样的:

ID    Name1    Name2    Group    
1234  A1       x        A
1234  A4       w        A
1234  A3       q        A
1234  A        A        A
1234  A2       z        A
5678  B3       s        B
5678  B        B        B
...

我不确定如何在数据框中执行此操作,以及从许多具有不同 ID 的行中执行此操作。我不想使用循环。

mutate()lapply() 可能吗?

我可以看到如何在 Group 列中为 Name1==Name2 的行添加 Name1 值,但是如何为所有匹配的 ID 回滚该值?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以在一行中使用data.table

    DT[, Group := Name1[Name1 == Name2], by=ID]
    

    详细信息:

    library(data.table)
    
    DT <- as.data.table(DF)
    
    DT[, Group := Name1[Name1 == Name2], by=ID]
    
         ID Name1 Name2 Group
    1: 1234    A1     x     A
    2: 1234    A4     w     A
    3: 1234    A3     q     A
    4: 1234     A     A     A
    5: 1234    A2     z     A
    6: 5678    B3     s     B
    7: 5678     B     B     B
    8: 1589     C     x    NA
    9: 1589     C     y    NA
    
    
    
    ## if `Name1`, `Name2`  are NOT characters, use 
    DT[, Name1 := as.character(Name1)]
    DT[, Name2 := as.character(Name2)]
    

    【讨论】:

      【解决方案2】:

      试试这个

      x <- merge(x, x[x$Name1 == x$Name2, 1:2], by.x = "ID", by.y = "ID")
      names(x)[4] <- "Group"
      #     ID Name1.x Name2   Group
      # 1 1234      A1     x       A
      # 2 1234      A4     w       A
      # 3 1234      A3     q       A
      # 4 1234       A     A       A
      # 5 1234      A2     z       A
      # 6 5678      B3     s       B
      # 7 5678       B     B       B
      

      【讨论】:

        【解决方案3】:

        另一种可能性:

        unsplit(lapply(split(df, df$ID), function(x) {
            x$Group <- if(any(y <- x$Name1 %in% x$Name2)) x$Name2[y] else NA
            x
        }), df$ID)
        
             ID Name1 Name2 Group
        1  1234    A1     x     A
        2  1234    A4     w     A
        3  1234    A3     q     A
        4  1234     A     A     A
        5  1234    A2     z     A
        6  5678    B3     s     B
        7  5678     B     B     B
        9  1589     C     x  <NA>
        10 1589     C     y  <NA>
        

        数据

        df <- 
        structure(list(ID = c("1234", "1234", "1234", "1234", "1234", 
        "5678", "5678", "1589", "1589"), Name1 = structure(c(2L, 5L, 
        4L, 1L, 3L, 7L, 6L, 8L, 8L), .Label = c("A", "A1", "A2", "A3", 
        "A4", "B", "B3", "C"), class = "factor"), Name2 = structure(c(6L, 
        5L, 3L, 1L, 7L, 4L, 2L, 6L, 8L), .Label = c("A", "B", "q", "s", 
        "w", "x", "z", "y"), class = "factor")), .Names = c("ID", "Name1", 
        "Name2"), row.names = c("1", "2", "3", "4", "5", "6", "7", "9", 
        "10"), class = "data.frame")
        

        【讨论】:

        • 我收到一条错误消息“组长度为零但数据长度> 0”
        【解决方案4】:

        每个 ID 在 Name1Name2 之间是否总是有一个(并且只有一个)匹配项?

        如果是这样,您可以为此使用 dplyr 中的mutate(在@Richard Scriven 的回答中使用df):

        require(dplyr)
        
        df[1:7,] %>% 
            group_by(ID) %>%
            mutate(Group = Name1[Name1 %in% Name2])
        

        如果每个 ID 可能有一个匹配项或没有匹配项,您可以添加一个 ifelse 语句来处理没有匹配项的情况。

        df %>% 
            group_by(ID) %>%
            mutate(Group = ifelse(any(Name1 %in% Name2), 
                                  as.character(Name1)[Name1 %in% Name2], "NA"))
        

        【讨论】:

        • 我在运行 mutate() 时不断收到错误消息:例如“大小不兼容 (3),需要 4(组大小)”。 ID 是左侧一些其他列的子集。但我将那些包含在我的 group_by() 中
        • @brno792 你能dput你的数据集(或其中的一部分)回答你的问题吗?听起来我没有考虑其他一些结构。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-13
        • 2020-08-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多