R - 通过唯一ID比较不同长度的数据帧中的列值

时间:2017-05-30 09:38:27

标签: r dataframe compare comparison multiple-columns

我确信我可以找到解决这个问题的简单方法,但我没有看到类似的问题,所以我想我会发一个问题。

我有一个纵向数据集,有数千名受访者在几个时间间隔内。从问题到数据类型的所有内容都可以在波浪之间有所不同,并且通常需要构建一系列长的bool来构建指标或虚拟变量,但每个受访者都有一个唯一的ID,没有其他受访者在第一次浪潮后添加到调查中,因此很容易够了。

问题是虽然早期波浪每个都由一个(Stata)文件组成,但后面的波浪包含许多附加文件,结构不同。因此,例如,在构建先前合作伙伴的性别的先前指标时,存在名为partnerNum和sex的列(针对一个波),并且每个唯一ID(响应者)最多有16行。很容易传播(或强制转换)该数据,以便能够为每个唯一ID和列partnerNum_1 ... partnerNum_16创建单行,并将sex列中的值作为partnerDF中的条目。然后很容易构建如下指标:

sexuality$newIndicator[mainDF$bioSex = "Male" & apply(partnerDF[1:16] == "Male", 1, any)] <- 1

对于最后两个波浪中的其他附录文件,数据的结构与合作伙伴数据一样长,每个唯一ID都有多行,但不是像性别这样的一个变量,我需要用数百个来测试构建指标,所有指标都用不同类型编码,因此传播(或转换)数据范围是不切实际的(不要介意编写那些bool)。实际上,每个wave都有几个这样的文件,并且它们的结构方式有些受访者(唯一ID)只占用一行,有些只有几十个。 (我已经为每一次浪潮留下了连接文件。)

我希望能够做的是测试类似的东西:

newDF$indicator[any(waveIIIAdds$var1 == 1) & any(waveIIIAdds$var2 == 1)] <- 1

newDF$indicator[mainDF$var1 == 1 & any(waveIIIAdds$var2 == 1)] <- 1

其中newDF与mainDF的长度相同(每个唯一ID一行)。

所以,例如,如果我有两个dfs。

df1 <- data.frame(ID = c(1:4), A = rep("a"))
df2 <- data.frame(ID = rep(1:4, each=2), B = rep(1:2, 2), stringsAsFactors = FALSE)
df1$A[1] <- "b"
df1$A[3] <- "b"
df2$B[8] <- 3

> df1   > df2
ID A    ID B
1  b    1  1
2  a    1  2
3  b    2  1
4  a    2  2
        3  1
        3  2
        4  1
        4  3

我想测试一下(假设df3有一列,只有df1中的唯一ID)

df3$new <- 0
df3$new[df1$ID[df1$A == "a"] & df2$ID[df2$B == 2]] <- 1

因此df3每行会有一个唯一的ID,因为df1 $ A中的所有ID都有一个“a”,但df1 $ A [1]和所有ID的df2 $ B中至少有一行中的2除了最后一个ID(df2 $ B [7:8]),结果将是:

> df3
ID new
1  0
2  1
3  1
4  0

df3$new <- 0
df3$new[df1$ID[df1$A == "a"] | df2$ID[df2$B == 2]] <- 1

> df3
ID new
1  1
2  1
3  1
4  0

2 个答案:

答案 0 :(得分:0)

这样做......

df3 <- data.frame(ID=unique(df1$ID),
                  new=sapply(unique(df1$ID),function(x) 
                     as.numeric(x %in% df1$ID[df1$A == "a"] & x %in% df2$ID[df2$B == 2])))

df3
  ID new
1  1   1
2  2   1
3  3   1
4  4   0

答案 1 :(得分:0)

在回到问题后(而不是帖子早上的凌晨时分),我想出了一个解决问题的简约解决方案几分钟。

我想要一个研究生,他可能会以这种方式构建数千个指标或虚拟变量,并且可能首先学习R,或者甚至只学习R,可以使用。以下提供了使用相同模式的示例和实际数据的解决方案:

如果DF已经使用ID创建,并且伪指示符的列值已经按照示例中的假设启动为零:

df3 <- data.frame(ID = df1$ID)
df3$new <- 0

我的解决方案是:

df3$new[df1$ID %in% df1$ID[df1$A == "a"] & df1$ID %in% df2$ID[df2$B == 2]] <- 1 

> df3
ID new
1   0
2   1
3   0
4   1

使用| (或)改为:

df3$new[df1$ID %in% df1$ID[df1$A == "a"] | df1$ID %in% df2$ID[df2$B == 2]] <- 1 

> df3
ID new
1   1
2   1
3   0
4   1