【问题标题】:Double match in rr中的双重匹配
【发布时间】:2015-11-20 02:17:02
【问题描述】:

我在 r 中有一个庞大的数据集,每个人一行。我的一个专栏显示了一个家庭标识符(注意,sex==1,男性,sex==2,女性)。

ind sex income  hw  family.id
1   1    10     6    fam.1
2   2    8      7    fam.1
3   2    15     8    fam.2
4   1    7      4    fam.3
5   2    9      5    fam.3

如何进行“双重匹配”,以便为我感兴趣的许多变量匹配数据集中的情侣?例如,假设个人 2,女性,与个人 1,男性结婚,应该在新列中收到他的收入条目(hw 也是如此):

ind sex income  hw  family.id  income.male   hw.male
1   1    10     6    fam.1       10            6
2   2    8      7    fam.1       8             6
3   2    15     8    fam.2       -             -
4   1    7      4    fam.3       7             7  
5   2    9      5    fam.3       9             7

我在标题中说了“双重匹配”,因为我不需要只匹配family.ID,但我需要找到一个匹配这个fam.id 的男性。我这样做的原因是因为以后所有男性都将从数据集中删除,我将只保留女性行。

很抱歉,我无法展示我编写过的任何代码。我尝试了许多使用 match 的方法,ifelselapply 甚至 unlist 但不值得在这里添加它,因为不幸的是我无法让它工作。

有人知道吗?我们可以使用data.framesdata.tables 环境。

【问题讨论】:

  • 在期望的结果中,为什么sex==2 的记录有income.malehw.male 的数据?
  • 嗨@Parfait6,因为这正是我正在寻找的:我想将匹配相同family.id 的sex==1 结果添加到sex==2 的行中。现在清楚了吗?
  • 我认为你应该使用dcast(DT, family.id ~ factor(sex, labels=c("male","female")), value.var=c("income","hw")),但不会发布它,因为你想要的输出是别的东西。 (这里的DT必须是data.table...)

标签: r if-statement data.table lapply


【解决方案1】:

您应该使用data.table 包。这是一个例子:

library(data.table)

dt <- data.table(ind = c(1, 2, 3, 4, 5), sex =c(1, 2, 2, 1, 2), income = c(10, 8, 15, 7, 9), hw = c(6, 7, 8, 4, 5), family.id = c('fam.1', 'fam.1', 'fam.2', 'fam.3', 'fam.3'))
setkeyv(dt, 'family.id')

dt2 <- dt[dt[sex == 1, list(family.id, income, hw)]]

它将采用男性 (dt[sex == 1, list(family.id, income, hw)]) 的 incomehw 并匹配 family.id 上的所有个人。结果你得到:

   ind sex income hw family.id i.income i.hw
1:   1   1     10  6     fam.1       10    6
2:   2   2      8  7     fam.1       10    6
3:   4   1      7  4     fam.3        7    4
4:   5   2      9  5     fam.3        7    4

前缀为i. 的列包含每个家庭的男性值。请注意,如果没有男性在场,您将不会收到任何行。如果你仍然需要这个,你可以这样做:

dt2 <- merge(dt, dt[sex == 1, list(family.id, income, hw)], by = 'family.id', suffixes = c('', '.i'), all = TRUE)

接收

   family.id ind sex income hw income.i hw.i
1:     fam.1   1   1     10  6       10    6
2:     fam.1   2   2      8  7       10    6
3:     fam.2   3   2     15  8       NA   NA
4:     fam.3   4   1      7  4        7    4
5:     fam.3   5   2      9  5        7    4

稍后当您需要删除男性数据时:

dt2[sex == 2]

【讨论】:

  • 这很好,但我建议尝试两个额外的改进:1)使用on=而不是设置密钥,2)使用:=更新而是直接dt
  • 非常感谢您的精彩回答。我知道我的解释不是最好的,所以也感谢你对我的理解!
  • 似乎在我的庞大数据集的情况下,合并结果的行数(我正在使用@danas.zuokas 提供的第二个选项,所以我可以保留那些如果 allow.cartesian 为 TRUE,则没有男性存在)远高于 max(nrow(x), nrow(i))。我认为增加行数没有意义。我的数据集一定有问题。
  • Labas rytas,@danas.zuokas。知道为什么我的组合会爆炸吗?另外,我不确定我们是否可以在这里问,但是您对 data.table 有任何具体的阅读提示(在包的正确文档的顶部)吗?
【解决方案2】:

假设数据框名为“dat”。您可以使用 merge 函数按 family.id 合并男性和女性。您提出的答案对我或其他评论者没有意义,但您可以在这个新对象中重新分配“收入”或“硬件”。

> merge( dat[ dat$sex==1, ], dat[dat$sex==2,] , by="family.id")
  family.id ind.x sex.x income.x hw.x ind.y sex.y income.y hw.y
1     fam.1     1     1       10    6     2     2        8    7
2     fam.3     4     1        7    4     5     2        9    5

【讨论】:

    【解决方案3】:

    跟进我的comment:

    require(data.table)
    dt[dt[sex == 1L], c("i.m", "hw.m") := .(i.income, i.hw), on="family.id"][]
    

    为每个family.id 提取sex == 'male' 所在的行索引,并通过引用添加两列与相应的incomehw 值。


    dt 在哪里:

    dt = fread('ind sex income  hw  family.id
    1   1    10     6    fam.1
    2   2    8      7    fam.1
    3   2    15     8    fam.2
    4   1    7      4    fam.3
    5   2    9      5    fam.3')
    

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2022-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多