匹配家庭伙伴,无循环

时间:2018-11-27 16:59:27

标签: r loops data.table

我试图避免使用loop来重新编码家庭伴侣的变量标识。

hldid表示家庭,而persid表示家庭中的人。 变量partner表示伙伴的persid,变量child表示该行是否为子级。

两个合作伙伴的变量partner中缺少的是persid

例如对于hldid == 1persid == 1的{​​{1}}的值为0,而应为partner

这是数据的样子:

2

我设法创建了一个非常丑陋的循环,但是对于整个数据集来说太慢了。

> test
   hldid persid age sex relresp partner child
1      1      1  26   2       0       0     0
2      1      2  26   1       1       1     0
3      2      1  59   2       0       0     0
4      2      2  64   1       1       1     0
5      3      1  76   2       0       0     0
6      4      1  65   2       0       0     0
7      4      2  64   1       1       1     0
8      5      1  52   2       0       0     0
9      5      2  51   1       1       1     0
10     5      3  20   2      21       0     1
11     5      4  14   2      21       0     1
12     7      1  69   1       0       0     0
13     7      2  70   2       1       1     0

您知道如何使用test$partnerREC = test$partner for(i in 1:13){ for(j in 1:13){ if( test$hldid[i] == test$hldid[i+1] & # verify if household is the same (test$persid[i] == test$partner[j]) ) { test$partnerREC[i] = test$persid[j] # put the persid for each partner } } } > test hldid persid age sex relresp partner child partnerREC 1 1 1 26 2 0 0 0 2 2 1 2 26 1 1 1 0 1 3 2 1 59 2 0 0 0 2 4 2 2 64 1 1 1 0 1 5 3 1 76 2 0 0 0 0 6 4 1 65 2 0 0 0 2 7 4 2 64 1 1 1 0 1 8 5 1 52 2 0 0 0 2 9 5 2 51 1 1 1 0 1 10 5 3 20 2 21 0 1 0 11 5 4 14 2 21 0 1 0 12 7 1 69 1 0 0 0 2 13 7 2 70 2 1 1 0 1 解决此问题吗?

data.table

6 个答案:

答案 0 :(得分:4)

可能的解决方案:

library(data.table)  # load the package
setDT(test)          # convert 'test' to a 'data.table'

test[, partnerREC := persid[c(pmin(2,.N):1,rep(0,(pmax(.N,2)-2)))] *
                       (persid %in% 1:2) *
                       (.N != 1)
     , by = hldid][]

给出:

> test
    hldid persid age sex relresp partner child partnerREC
 1:     1      1  26   2       0       0     0          2
 2:     1      2  26   1       1       1     0          1
 3:     2      1  59   2       0       0     0          2
 4:     2      2  64   1       1       1     0          1
 5:     3      1  76   2       0       0     0          0
 6:     4      1  65   2       0       0     0          2
 7:     4      2  64   1       1       1     0          1
 8:     5      1  52   2       0       0     0          2
 9:     5      2  51   1       1       1     0          1
10:     5      3  20   2      21       0     1          0
11:     5      4  14   2      21       0     1          0
12:     7      1  69   1       0       0     0          2
13:     7      2  70   2       1       1     0          1

此解决方案基于以下假设(从示例数据中得出):只有“ perid” 1和2是伙伴,更高的是孩子。

这是什么:

  • hldid分组
  • 在一个家庭中更改前两个人的顺序,但前提是一个家庭中有更多人 persid[c(pmin(2,.N):1,rep(0,(pmax(.N,2)-2)))],其中pmin用于确保当一个家庭只有一个人时构造长度为1的向量。
  • 将其乘以(persid %in% 1:2)可获得儿童的动物园动物。
  • (.N != 1)乘以一个人的家庭的零值。

答案 1 :(得分:1)

df <- data.frame(matrix(data = NA, ncol = 7))
names(df) <- names(test)

for(id in unique(test$hldid)){
  t <- test[test$hldid==id,]
  t$partner[t$persid == t$partner[t$partner!=0]] <- t$persid[which(t$partner!=0)]

  df <- rbind(df, t)
}

df <- df[-1,]

答案 2 :(得分:1)

基本的R解决方案比Jaap的data.table solution更复杂。

我正在处理副本。

test2 <- test

运行问题代码后,运行以下代码。

test2$partnerREC <- test2$partner
sp <- split(test2, test2$hldid)
test2 <- lapply(sp, function(DF){
  i <- with(DF, which(persid %in% partner))
  j <- with(DF, which(partner %in% persid))
  #cat("i:", i, "\tj:", j, "\n")
  DF$partnerREC[i] <- DF$persid[j]
  DF
})
test2 <- do.call(rbind, test2)
row.names(test2) <- NULL

现在比较两个结果。

identical(test, test2)
#[1] TRUE

答案 3 :(得分:0)

您可以通过一些dplyr步骤到达那里,以结合自身的数据并在persid == partner时更新partner的值。

test2 <- left_join(test, test %>% select(hldid, persid, partner) %>% filter(partner != 0), by=c("hldid")) %>%
  filter(persid.x == partner.y) %>%
  mutate(partner.x = persid.y)

这将使您的户主的伴侣ID匹配,但是您必须将其重新加入原始数据(我不确定dplyr lingo中的SQL update等同)。< / p>

答案 4 :(得分:0)

1。创建测试数据。frame

 library(tidyverse)

 test <- tribble(
            ~hldid, ~persid, ~age, ~sex, ~relresp, ~partner, ~child,
             1,      1,     26,   2,       0,       0,         0,
             1,      2,     26,   1,       1,       1,         0,
             2,      1,     59,   2,       0,       0,         0,
             2,      2,     64,   1,       1,       1,         0,
             3,      1,     76,   2,       0,       0,         0,
             4,      1,     65,   2,       0,       0,         0,
             4,      2,     64,   1,       1,       1,         0,
             5,      1,     52,   2,       0,       0,         0,
             5,      2,     51,   1,       1,       1,         0,
             5,      3,     20,   2,      21,       0,         1,
             5,      4,     14,   2,      21,       0,         1,
             7,      1,     69,   1,       0,       0,         0,
             7,      2,     70,   2,       1,       1,         0)

2。 arrange() group_by() mutate()来营救

test %>%
  # arrange the data in case the raw data did not 
  arrange(hldid, child, persid) %>%
  # group each household 
  group_by(hldid) %>%
  # match first and second household person as each other's partner
  mutate(partnerREC = ifelse(persid == first(persid), nth(persid, 2), first(persid))) %>%
  # correct partnerREC for child and single 
  mutate(partnerREC = ifelse(child == 1 | is.na(partnerREC), 0, partnerREC))
  # un-group it
  ungroup() 

答案 5 :(得分:0)

使用$val = "sgadjgjsd".($array['c'] ?? ''); 的{​​{1}}解决方案

使用loop脚本

rcpp

并运行功能

rcpp

第一种情况(如果您知道如何解决)只有一点点问题