【问题标题】:R - Create a new variable where each observation depends on another table and other variables in the data frameR - 创建一个新变量,其中每个观察值都依赖于另一个表和数据框中的其他变量
【发布时间】:2016-02-15 16:10:30
【问题描述】:

我有以下两个表:

df <- data.frame(eth = c("A","B","B","A","C"),ZIP1 = c(1,1,2,3,5))
Inc <- data.frame(ZIP2 = c(1,2,3,4,5,6,7),A = c(56,98,43,4,90,19,59), B = c(49,10,69,30,10,4,95),C = c(69,2,59,8,17,84,30))

eth    ZIP1         ZIP2    A    B    C
A      1            1      56   49   69
B      1            2      98   10   2
B      2            3      43   69   59
A      3            4      4    30   8
C      5            5      90   10   17
                    6      19   4    84
                    7      59   95   39

我想在 df 数据框中创建一个变量 Inc ,其中对于每个观察,值是观察的 eth 和 ZIP 的交集。在我的示例中,它会导致:

   eth    ZIP1   Inc        
    A      1    56
    B      1    49
    B      2    10
    A      3    43
    C      5    17

循环或蛮力可以解决它,但我的数据集需要时间,我正在寻找一种更微妙的方法,可能使用 data.table。在我看来,这是一个非常标准的问题,如果是,我很抱歉,我无法为这个问题制定一个精确的标题(你可能已经注意到了..)也许是我没有找到任何类似问题的原因在论坛搜索..

谢谢!

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    当然,可以在data.table中完成:

    library(data.table)
    setDT(df)
    
    df[ melt(Inc, id.var="ZIP2", variable.name="eth", value.name="Inc"), 
      Inc := i.Inc
    , on=c(ZIP1 = "ZIP2","eth") ]
    

    这个“合并分配”操作的语法是X[i, Xcol := expression, on=merge_cols]

    您可以自行运行i = melt(Inc, id.var="ZIP", variable.name="eth", value.name="Inc") 部分,看看它是如何工作的。在合并内部,来自i 的列可以用i.* 前缀引用。


    交替...

    setDT(df)
    setDT(Inc)
    df[, Inc := Inc[.(ZIP1), eth, on="ZIP2", with=FALSE], by=eth]
    

    这是基于类似的想法。 The package vignettes 是开始使用这种语法的好地方。

    【讨论】:

    • 谢谢。我会尽力理解其中的逻辑。但是,它似乎不起作用,但这是我的错:我更新了帖子以分隔第一张和第二张表的 ZIP。我应该在你的公式中选择哪一个?错误是:“未使用的参数(on = c(“ZIP1”,“eth”))”
    • @Julien 好的,我已经针对这种情况进行了更新。我不确定它是否适用于 data.table 1.9.6(我正在运行开发版本)。如果您先运行setDT 行,则未使用的参数将被修复。
    • 感谢您的参考,这对我非常有用!即使在使用 setDT 时,您的解决方案似乎仍然存在相同的崩溃。但是我会努力理解更多使用 data.tables 的合并,从长远来看它对我很有用:)
    【解决方案2】:

    我们可以使用row/column索引

    df$Inc <- Inc[cbind(match(df$ZIP1, Inc$ZIP2), match(df$eth, colnames(Inc)))]
    
    df
    #  eth ZIP1 Inc
    #1   A    1  56
    #2   B    1  49
    #3   B    2  10
    #4   A    3  43
    #5   C    5  17
    

    【讨论】:

      【解决方案3】:

      这个怎么样?

      library(reshape2)
      merge(df, melt(Inc, id="ZIP2"), by.x = c("ZIP1", "eth"), by.y = c("ZIP2", "variable"))
        ZIP1 eth value
      1    1   A    56
      2    1   B    49
      3    2   B    10
      4    3   A    43
      5    5   C    17
      

      【讨论】:

      • 好的,非常感谢!我还是个新手,还没有认真考虑使用这些函数 :) 只是崩溃说 x 和 y 的变量必须对应。我将它们的名称更改为相同但它仍然崩溃然后我使用简单的“by”而不是“by.x by.y”并且它起作用了。
      【解决方案4】:

      另一种选择:

      library(dplyr)
      library(tidyr)
      Inc %>%
        gather(eth, value, -ZIP2) %>%
        left_join(df, ., by = c("eth", "ZIP1" = "ZIP2"))
      

      【讨论】:

        【解决方案5】:

        我的解决方案(可能看起来很尴尬)

        for (i in 1:length(df$eth)) {
            df$Inc[i] <- Inc[as.character(df$eth[i])][df$ZIP[i],]
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-15
          • 2019-01-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多