如何使用dplyr操纵长表数据以进行相关,但不将数据转换为宽格式

时间:2015-09-04 07:13:47

标签: r dplyr tidyr

我有一些数据表示患者(id)的重复(会话A和B)测量值(var.x)。我的数据很整洁(即每个列中有一个变量,每行有一个变量的长表)......就像这样:

| id | var.1 | var.2 | session |
--------------------------------
|  1 |  1.1  |   11  |    A    |
|  1 |  1.9  |   12  |    B    |
|  2 |  1.2  |   15  |    A    |
|  2 |  1.4  |   14  |    B    |

我想对会话A和B的配对(通过id)数据(例如var.1)进行相关分析。换句话说,重复测量之间的相关系数是多少。

这不难做到,如果我将数据转换/旋转/融合/传播到如下的宽格式:

| id | var.1.A | var.2.A | var.1.B | var.2.B |
----------------------------------------------
|  1 |  1.1    |   11    |   1.9   |   12    |
|  2 |  1.2    |   15    |   1.4   |   14    |

...然后我可以简单地用cor(var.1.A,var.1.B)。而且我意识到dplyr / tidyr已经为此目的收集/传播/分离/联合命令,但是这对我来说似乎不整洁且不太优雅,因为我基本上必须复制我的数据。

有没有办法使用dplyr执行此操作,而无需重新整形数据?

我正在考虑以下几点:

data %>% 
    select(id, var.1, session) %>%
    do( cor( filter(session=='A', filter(session=='B')) 

...但显然这不起作用,我还需要以某种方式指定数据配对(通过id)。

2 个答案:

答案 0 :(得分:1)

我想我会使用 dplyr 中的summarise_each添加一个答案,说明如何执行此操作。

此方法取决于数据集顺序。在这种情况下,我喜欢使用arrange来确保数据集符合所需的顺序,但如果您确信这些数据集已经有序,则可以跳过此数据集。

data %>%
    arrange(id, session) %>%
    summarise_each(funs(cor(.[session == "A"], .[session == "B"])), starts_with("var"))

  var.1 var.2
1    -1     1

summarise_each中,.指的是您要汇总的变量,其中do指的是数据集。

您可以简单地写出要按名称汇总的变量,但我使用函数starts_with来选择变量。有关这些特殊功能的更多信息,请参阅select的帮助页面。

您还需要确保每个ID中都有一对。如果遇到complete中缺少某个session级别的情况,则 tidyr 包中的id函数可能会有用。如果是这种情况,您可能需要在use中使用cor参数。

答案 1 :(得分:0)

我们可以尝试使用dplyrdata.table方法。假设我们想要找到'var'列的相关性,我们使用grep('nm1')和自定义函数(f1)创建列的索引。我们在Map中使用do来获取每个'var'列的cor。我们使用'var'列作为第一个输入,即'x'和'session'作为'y'。

nm1 <- grep('^var', names(data))
f1 <- function(x,y) cor(x[y=='A'], x[y=='B']) 
library(dplyr)
data %>% 
      do({data.frame(Map(f1, .[nm1], list(.$session)))})
#   var.1 var.2
#1    -1     1

以类似的方式,我们可以使用cor执行data.table

library(data.table)
setDT(data)[, Map(f1, .SD[, nm1, with=FALSE], list(session)) ]
#   var.1 var.2
#1:    -1     1

如果我们使用base R

mapply(f1, data[nm1], list(data$session))
# var.1 var.2 
# -1     1 

如果我们想要转换为wide格式,我们可以使用dcast的devel版本中的data.table,即v1.9.5,因为它可能需要多个value.var列。

 dW <- dcast(setDT(data), id~session, value.var=c('var.1', 'var.2'))[, id:=NULL]
 dW
 #   var.1_A var.1_B var.2_A var.2_B
 #1:     1.1     1.9      11      12
 #2:     1.2     1.4      15      14

我们可以转换为matrix,子集,应用cor并获取diag值。

 m1 <- as.matrix(dW)
 diag(cor(m1[,c(TRUE, FALSE)], m1[,c(FALSE, TRUE)]))
 #[1] -1  1

数据

data <- structure(list(id = c(1L, 1L, 2L, 2L), var.1 = c(1.1, 1.9, 1.2, 
1.4), var.2 = c(11L, 12L, 15L, 14L), session = c("A", "B", "A", 
"B")), .Names = c("id", "var.1", "var.2", "session"), 
class = "data.frame", row.names = c(NA, -4L))