【问题标题】:Issue with indexing using two data frames in R在 R 中使用两个数据帧进行索引的问题
【发布时间】:2019-03-18 03:31:28
【问题描述】:

我有两个数据框 Table_1Table_2,我需要在 Table_2 中添加一列 "index",其中值 1 用于匹配来自 Table_1 的行,而 0 用于匹配其他行。

基本上,我需要匹配 Table_1 中的“Pol”、“CTY”、“STATE”和“CRP”列以及 Table_2 中的“STATE”、“CTY”、“CRP”和“Pol_No”。

我更喜欢 data.table 方法。

 Table_1:

 Pol      Cty    Avg    STATE   CRP
 85010    23     1123    MO     11
 75022    23     1123    MO     11
 35014   143     450     MO     11
.
.

Table_2:

STATE   CTY    CRP   Pol_No   Plan   Price 
AL      1      11    150410   90     4563
AL      1      21    45023    90     5402
MO    143      11    85010    90     2522
.
.

所需的输出如下。

Table_2:

STATE   CTY    CRP   Pol_No   Plan   Price  Index
AL      1      11    150410   90     4563     0
AL      1      21    45023    90     5402     0
MO    143      11    85010    90     2522     1
.
.

我怎样才能实现这是 R.?

感谢任何帮助。

谢谢。

【问题讨论】:

    标签: r dataframe indexing


    【解决方案1】:

    这是一个完整的 data.table 解决方案:

     merge(t1,t2,by.x='Pol', by.y='Pol_No', all.y=TRUE)[,c('STATE.y','CTY', 'Cty', 'CRP.y',   'Pol',   'Plan',   'Price')]
    #-----
       STATE.y CTY Cty CRP.y    Pol Plan Price
    1:      AL   1  NA    21  45023   90  5402
    2:      MO 143  23    11  85010   90  2522
    3:      AL   1  NA    11 150410   90  4563
    #--------
    t3 <- merge(t1,t2,by.x='Pol', by.y='Pol_No', all.y=TRUE)[ ,
              c('STATE.y','CTY', 'Cty', 'CRP.y', 'Pol', 'Plan',   'Price')] 
    t3[ , index := as.numeric(!is.na(Cty))]
    t3
    #--------
       STATE.y CTY Cty CRP.y    Pol Plan Price index
    1:      AL   1  NA    21  45023   90  5402     0
    2:      MO 143  23    11  85010   90  2522     1
    3:      AL   1  NA    11 150410   90  4563     0
    

    merge(.. 之后获取列名,我首先查看了:

    merge(t1,t2,by.x='Pol', by.y='Pol_No', all.y=TRUE)
          Pol Cty  Avg STATE.x CRP.x STATE.y CTY CRP.y Plan Price
    1:  45023  NA   NA    <NA>    NA      AL   1    21   90  5402
    2:  85010  23 1123      MO    11      MO 143    11   90  2522
    3: 150410  NA   NA    <NA>    NA      AL   1    11   90  4563
    

    【讨论】:

      【解决方案2】:

      我认为这是一个直接的多列连接:​​

      library(dplyr)
      t2 %>%
        left_join(transmute(t1, CTY=Cty, STATE, Index=1L), by=c("CTY", "STATE")) %>%
        mutate(Index = if_else(is.na(Index), 0L, Index))
      #   STATE CTY CRP Pol_No Plan Price Index
      # 1    AL   1  11 150410   90  4563     0
      # 2    AL   1  21  45023   90  5402     0
      # 3    MO 143  11  85010   90  2522     1
      

      编辑

      我一直在努力学习data.table,我想试试这个。我觉得它有点笨拙,我相信有一种方法可以简化它。

      t1 <- setDT(t1); t2 <- setDT(t2)
      

      为方便起见,将列名设置为相同(否则我不确定如何轻松实现)...一个是"Cty",另一个是"CTY"。使它们相同。

      colnames(t1)[2] <- "CTY"
      

      现在,合并。

      t1[,.(CTY,STATE,CRP,Index=1),][t2,on=c("CTY","STATE","CRP")]
      #    CTY STATE CRP Index Pol_No Plan Price
      # 1:   1    AL  11    NA 150410   90  4563
      # 2:   1    AL  21    NA  45023   90  5402
      # 3: 143    MO  11     1  85010   90  2522
      

      注意事项:

      • 第一个括号操作只选择三个连接列并分配第四个,Index
      • 实际连接在第二个括号操作中,第一个只是一个选择
      • 通常data.table ops 会产生副作用,但不会像这样进行合并或选择,因此它会在不修改底层结构的情况下返回它;为此,我们需要将其存储(可能返回到 t2

      已经接近了...现在只需更新 Index 字段,因为它要么是数据共存的 1,要么是 NA

      t2 <- t1[,.(CTY,STATE,CRP,Index=1),][t2,on=c("CTY","STATE","CRP")]
      t2[,Index := as.integer(!is.na(Index)),]
      t2
      #    CTY STATE CRP Index Pol_No Plan Price
      # 1:   1    AL  11     0 150410   90  4563
      # 2:   1    AL  21     0  45023   90  5402
      # 3: 143    MO  11     1  85010   90  2522
      

      数据:

      t1 <- read.table(header=TRUE, stringsAsFactors=FALSE, text='
       Pol      Cty    Avg    STATE   CRP
       85010    23     1123    MO     11
       75022    23     1123    MO     11
       35014   143     450     MO     11')
      t2 <- read.table(header=TRUE, stringsAsFactors=FALSE, text='
      STATE   CTY    CRP   Pol_No   Plan   Price 
      AL      1      11    150410   90     4563
      AL      1      21    45023    90     5402
      MO    143      11    85010    90     2522')
      

      【讨论】:

      • 这似乎是正确的。加入时也应考虑CRP。但是,我更喜欢 data.table 方法。
      • 您的文本、数据或代码中没有任何内容表明您正在使用或想要使用data.table。也许你应该更新你的问题。抱歉,我省略了CRP,但坦率地说(1)将它添加到by= 参数和transmute 调用是微不足道的,并且(2)如果你想要data.table,那么这个答案无论如何都会消失。
      • 我忘了包括在上面的文字中。对不起,这是我的错。无论如何,谢谢。
      • 我也有一个惊人的答案,但它只适用于数据框哈哈
      【解决方案3】:

      这不是一个好的解决方案,但它适用于data.table。您需要sqldf,它适用于数据框和数据表。

      library(data.table)
      df1<-data.table(Pol=c(85010,75022,35014),Cty=c(23,23,143), Avg=c(1123,1123,450),STATE=c("MO","MO","MO"), CRP=c(11,11,11))
      
      df2=data.table(STATE=c("AL","AL","MO"),CTY=c(1,1,143),CRP=c(11,21,11),Pol_No=c(150410,45023,85010),Plan=c(90,90,90),Price=c(4563,5402,2522))
      
      library(sqldf)
      #left join
      df<-sqldf("select df2.STATE,df2.CTY,df2.CRP,df2.Pol_No,df2.Plan,df2.Price,df1.Pol from df2 left join df1 on df1.Pol=df2.Pol_No")
      #create index
      df$index<-ifelse(is.na(df$Pol),0,1)
      
      #delete extra column
      df$Pol<-NULL 
      
      > df
        STATE CTY CRP Pol_No Plan Price index
      1    AL   1  11 150410   90  4563     0
      2    AL   1  21  45023   90  5402     0
      3    MO 143  11  85010   90  2522     1
      

      【讨论】:

      • 对不起。我不打算编辑你的并把它颠倒了。
      猜你喜欢
      • 1970-01-01
      • 2019-10-17
      • 2018-10-30
      • 2023-02-03
      • 2020-08-20
      • 1970-01-01
      • 2023-03-25
      • 2018-12-11
      • 1970-01-01
      相关资源
      最近更新 更多