2

我有一个包含三个变量的数据框:治疗、剂量和结果(正负)。我对每种治疗和剂量都有多个观察结果。我正在尝试输出一个列联表,该表将折叠数据以指示每个结果的数量作为治疗和剂量的函数,以及观察的数量。例如:

treatment dose outcome    
control 0 0
control 0 0
control 0 0
control 0 1
treatmentA 1 0
treatmentA 1 1
treatmentA 1 1
treatmentA 2 1
treatmentA 2 1 
treatmentA 2 1

所需的输出将是:

treatment dose outcome n
control 0 0 1 4
treatmentA 1 2 3
treatmentA 2 3 3

我一整天都在玩这个,除了能够为每次观察获得每个结果的频率之外,没有太多运气。任何建议将不胜感激(包括指出 R 手册和/或示例的哪些部分)我忽略了。

谢谢!

R

4

5 回答 5

5

这是一个使用了不起的包的解决方案data.table

library(data.table)
x <- data.table(read.table( text = "treatment dose outcome    
control 0 0
control 0 0
control 0 0
control 0 1
treatmentA 1 0
treatmentA 1 1
treatmentA 1 1
treatmentA 2 1
treatmentA 2 1 
treatmentA 2 1", header = TRUE)
x[, list(outcome = sum(outcome), count = .N), by = 'treatment,dose']

生产

    treatment dose outcome count
1:    control    0       1     4
2: treatmentA    1       2     3
3: treatmentA    2       3     3
于 2013-01-29T01:38:34.433 回答
4

如果您不想按照其他答案中的建议使用额外的库,可以尝试以下操作。

> df
    treatment dose outcome
1     control    0       0
2     control    0       0
3     control    0       0
4     control    0       1
5  treatmentA    1       0
6  treatmentA    1       1
7  treatmentA    1       1
8  treatmentA    2       1
9  treatmentA    2       1
10 treatmentA    2       1

> dput(df)
structure(list(treatment = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L), .Label = c("control", "treatmentA"), class = "factor"), 
    dose = c(0L, 0L, 0L, 0L, 1L, 1L, 1L, 2L, 2L, 2L), outcome = c(0L, 
    0L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L)), .Names = c("treatment", 
"dose", "outcome"), class = "data.frame", row.names = c(NA, -10L
))

现在我们使用aggregate函数来获取outcome列的计数和总和

> nObs <- aggregate(outcome ~ treatment + dose, data = df, length)
> sObs <- aggregate(outcome ~ treatment + dose, data = df, sum)

适当更改聚合列的名称

名称(nObs)<-c('治疗','剂量','计数')

> names(sObs) <- c('treatment', 'dose', 'sum')

> nObs
   treatment dose count
1    control    0     4
2 treatmentA    1     3
3 treatmentA    2     3


> sObs
   treatment dose sum
1    control    0   1
2 treatmentA    1   2
3 treatmentA    2   3

在这种情况下,用于merge将以上两个同名的所有列组合起来treatmentdose

> result <- merge(nObs, sObs)
> result
   treatment dose count sum
1    control    0     4   1
2 treatmentA    1     3   2
3 treatmentA    2     3   3
于 2013-01-29T01:36:37.680 回答
3

如果我理解正确,这对data.table图书馆来说很简单。首先,加载库并读取数据:

library(data.table)

data <- read.table(header=TRUE, text="
treatment dose outcome    
control 0 0
control 0 0
control 0 0
control 0 1
treatmentA 1 0
treatmentA 1 1
treatmentA 1 1
treatmentA 2 1
treatmentA 2 1 
treatmentA 2 1")

接下来,data.table使用treatmentdose列作为表键(索引)创建一个。

data <- data.table(data, key="treatment,dose")

data.table然后使用语法聚合。

data[, list(outcome=sum(outcome), n=length(outcome)), by=list(treatment,dose)]

    treatment dose outcome n
1:    control    0       1 4
2: treatmentA    1       2 3
3: treatmentA    2       3 3
于 2013-01-29T01:36:28.800 回答
2

这是另外几个选项(即使认为该data.table方法在语法简洁方面明显胜出)。

第一次使用ave. 可以将函数应用于由一个或多个变量分组的变量(提到的第一个变量)。在删除现在不必要的“结果”列后,我们将输出包装起来。withinaveunique

unique(within(df, {
  SUM <- ave(outcome, treatment, dose, FUN = sum)
  COUNT <- ave(outcome, treatment, dose, FUN = length)
  rm(outcome)
}))
#    treatment dose COUNT SUM
# 1    control    0     4   1
# 5 treatmentA    1     3   2
# 8 treatmentA    2     3   3

基础 R 中的第二个解决方案与@geektrader 的答案非常相似,除了它在一次调用聚合中sum计算两者。length但是有一个“缺点”:结果cbind是您的“列”data.frame实际上是一个矩阵。查看结果str以了解我的意思。

temp <- aggregate(outcome ~ treatment + dose, df, 
                  function(x) cbind(sum(x), length(x)))
str(temp)
# 'data.frame':  3 obs. of  3 variables:
#  $ treatment: Factor w/ 2 levels "control","treatmentA": 1 2 2
#  $ dose     : int  0 1 2
#  $ outcome  : int [1:3, 1:2] 1 2 3 4 3 3

colnames(temp$outcome) <- c("SUM", "COUNT")
temp
#    treatment dose outcome.SUM outcome.COUNT
# 1    control    0           1             4
# 2 treatmentA    1           2             3
# 3 treatmentA    2           3             3

我提到存储结构是一个“缺点”,主要是因为当您尝试以您可能习惯的方式访问数据时,您可能无法获得预期的结果。

temp$outcome.SUM
# NULL

temp$outcome
#      SUM COUNT
# [1,]   1     4
# [2,]   2     3
# [3,]   3     3

相反,您必须通过以下方式访问它:

temp$outcome[, "SUM"] ## or temp$outcome[, 1]
# [1] 1 2 3
于 2013-01-29T04:35:22.727 回答
2

恕我直言,sql被低估了。:)

# read in your example data as `x`
x <- read.table( text = "treatment dose outcome    
control 0 0
control 0 0
control 0 0
control 0 1
treatmentA 1 0
treatmentA 1 1
treatmentA 1 1
treatmentA 2 1
treatmentA 2 1 
treatmentA 2 1",h=T)

# load the sql data frame library
library(sqldf)

# create a new table of all unique `treatment` and `dose` columns,
# summing the `outcome` column and 
# counting the number of records in each combo
y <- sqldf( 'SELECT treatment, dose , 
                    sum( outcome ) as outcome , 
                    count(*) as n 
             FROM   x 
             GROUP BY treatment, dose' )

# check the results
y
于 2013-01-29T01:19:16.307 回答