【问题标题】:Finding values in data frame based on another data frame in R基于R中的另一个数据框在数据框中查找值
【发布时间】:2020-04-21 08:50:00
【问题描述】:

刚从 R 开始(以及一般的编码)...我在使用两个不同的数据帧时遇到了这个计算问题,但我找不到解决方案。我为我的问题创建了一个简化示例:

我有两个数据框,df_1 和 df_2:

df_1:

  Numbers     Assigned_color
        1                  -
        2                  -
        3                  -
        4                  -
        5                  -
        6                  -

df_2:

  Value     Color
      4      Blue
      5    Orange
      6       Red

我想要的是根据使用两个数据帧中的值的函数为 df_1 中的数字分配颜色。在此示例中,如果 df_1$Numberdf_2$Value 的总和等于 10,我希望分配颜色。这将导致以下结果 (df_1):

  Numbers     Assigned_color
        1                  -
        2                  -
        3                  -
        4                Red
        5             Orange
        6               Blue

我得到的最接近的是:

for(i in 2:nrow(df_1)) {
  for(j in 2:nrow(df_2)) {

       df_1$Assigned_color[i] <- ifelse(df_1$Numbers[i] + df_2$Value[j] == 10,
       df_2$Color[j],
       df_1$Assigned_color[i])

  }}

但是不起作用,因为我得到的结果是这样的:

  Numbers     Assigned_color
        1                  -
        2                  -
        3                  -
        4                Red
        5             Orange
        6                  -

...我不明白为什么。非常感谢您的耐心等待。

编辑:真正的功能要复杂得多,数据集也很大。对不起,我应该提到这一点。我实际上正在寻找的是脚本,我可以在其中输入任何类型的长复杂函数并根据值分配“颜色”,如下所示:

for(i in 2:nrow(df_1)) {
  for(j in 2:nrow(df_2)) {

       df_1$Assigned_color[i] <- ifelse
       [very long function using values from both dataframes] == [desired value],
       df_2$Color[j],
       df_1$Assigned_color[i])

  }}

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用 dplyr 加入数据并获得相同的结果;

    library(dplyr)
    
    df_1 <-
      data.frame(
        Numbers = c(1,2,3,4,5,6),
        Assigned_color = c(NA_character_,NA_character_,NA_character_,
                           NA_character_,NA_character_,NA_character_),
        stringsAsFactors = FALSE
      )
    
    df_2 <-
      data.frame(
        Value = c(4,5,6),
        Color = c("Blue", "Orange", "Red"),
        stringsAsFactors = FALSE
      )
    
    df_1 %>%
      left_join(df_2, by = c("Numbers" = "Value")) %>%
      mutate(Value = ifelse(!is.na(Color), Numbers, NA),
             Color = ifelse(Value + Numbers == 10, Color, NA_character_)) %>%
      select(Numbers, Color)
    
    #Numbers  Color
    # 1   <NA>
    # 2   <NA>
    # 3   <NA>
    # 4   Blue
    # 5 Orange
    # 6    Red
    

    【讨论】:

    • 谢谢!如果我错了,请纠正我,但我认为这只有在我想对变量求和时才有效。抱歉,我没有提到实际问题中的功能要复杂得多。是否有一种解决方案,我可以使用任何带有 ifelse 函数的公式,甚至可以更改它?
    • 您可以在变异步骤中创建任何您想要的公式。我已经对其进行了编辑以展示您如何做到这一点。
    • 好的,非常感谢,明天我得再看看(我几乎不明白脚本中发生了什么)
    【解决方案2】:

    base R 选项是在转换为逻辑矩阵 ('m1') 后获取外部总和的行/列索引,然后根据索引进行分配

    m1 <- outer(df_2$Value, df_1$Numbers, `+`) == 10
    i1 <- which(m1, arr.ind = TRUE)
    df_1$Assigned_color[i1[,2]] <- df_2$Color[i1[,1]]
    df_1
    #  Numbers Assigned_color
    #1       1              -
    #2       2              -
    #3       3              -
    #4       4            Red
    #5       5         Orange
    #6       6           Blue
    

    数据

    df_1 <- structure(list(Numbers = 1:6, Assigned_color = c("-", "-", "-", 
    "-", "-", "-")), class = "data.frame", row.names = c(NA, -6L))
    
    df_2 <- structure(list(Value = 4:6, Color = c("Blue", "Orange", "Red"
    )), class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

      【解决方案3】:

      如果写成sql查询,可以写两个表之和必须为10的条件作为两个表的连接条件,然后用这些结果对原表做反连接,得到不匹配的数字, 并将匹配项和不匹配项绑定在一起。

      library(sqldf)
      
      matches <-  sqldf('
        select  a.Numbers
                , b.Color as Assigned_color
        from    df_1 a
                join df_2 b
                  on a.Numbers + b.Value = 10
        ')
      nonmatches <-  sqldf('
        select  a.*
        from    df_1 a 
                left join matches b
                  on a.Numbers = b.Numbers
        where   b.Numbers is NULL
        ')
      
      rbind(nonmatches, matches)
      #   Numbers Assigned_color
      # 1       1              -
      # 2       2              -
      # 3       3              -
      # 4       4            Red
      # 5       5         Orange
      # 6       6           Blue
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-27
        • 2021-09-19
        • 2016-05-07
        • 2016-08-18
        • 1970-01-01
        • 2021-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多