使用每行的条件在data.frame中创建一个新列

时间:2010-08-23 11:06:33

标签: r where-clause dataframe

我有一个R数据框:

> tab1
  pat  t conc
1  P1  0  788
2  P1  5  720
3  P1 10  655
4  P2  0  644
5  P2  5  589
6  P2 10  544

我正在尝试为conc创建一个新列,作为每个患者conc = 0的t的百分比。除了许多其他事情,我还尝试过:

tab1$conct0 <- tab1$conc / tab1$conc[tab1$t == 0  & tab1$pat == tab1$pat]

但我显然已经使用了正确的代码,这意味着“conc WHERE t == 0并且pat = =拍拍这个特定的行”

我确信我可以使用for循环或其他东西,但希望有更容易的东西?

由于

5 个答案:

答案 0 :(得分:2)

使用plyr:

library(plyr)
ddply(tab1, "pat", transform, conct0 = conc / conc[t == 0])

答案 1 :(得分:1)

我会找到每位患者的起始浓度:

startConc <- tab1[tab1$t == 0,]

给出(来自您的示例数据)

  pat t conc
1  P1 0  788
4  P2 0  644

之后,您可以使用apply

newconc <- apply(tab1, 1, function(x){as.numeric(x[3])/startConc[startConc$pat==x[1],3]})

给你

[1] 1.0000000 0.9137056 0.8312183 1.0000000 0.9145963 0.8447205

答案 2 :(得分:1)

这是一种稍微简单的方法,但在这种情况下有效:

xt <- xtabs(conc~t+pat,tab1)
tab1$conct0 <- as.numeric(t(t(xt)/xt[1,])) # need to use transpose because of the way matrix vector indexing works

xt[1,]代表t=0的行;你也可以使用xt["0",]

修改

更强大的方式:

tabt <- subset(tab1,t==0)
names(tabt)[3] <- "conct0"
tab1 <- merge(tab1,tabt[,c(1,3)])
tab1$conct0 <- tab1$conc/tab1$conct0

答案 3 :(得分:1)

我会使用tapply。鉴于您的数据:

tab1 <- data.frame(
    pat = c(rep("P1", 3), rep("P2", 3)),
    t = c(0, 5, 10, 0, 5, 10),
    conc = c(788, 720, 655, 644, 589, 544))

这个单行代码将按照你在帖子中暗示的方式为你做这件事:

> tab1$conc / tab1$conc[tab1$t == 0][tapply(tab1$pat, tab1$pat)]
[1] 1.0000000 0.9137056 0.8312183 1.0000000 0.9145963 0.8447205

没有任何函数的tapply创建一个与每行的患者ID(数字)匹配的行索引。我发现这种方法相当快速有用。但这假设您的患者'被命令。如果这是一个问题,我们可以确保它们符合患者的ID顺序:

> tab1$conc / tab1$conc[tab1$t == 0][order(unique(tab1$pat))][tapply(tab1$pat, tab1$pat)]
[1] 1.0000000 0.9137056 0.8312183 1.0000000 0.9145963 0.8447205

如果您经常使用它,我会为它编写一个函数,例如:

myFract <- function(obj, x = "conc", id = "pat", time = "t", start = NULL) {
    if (is.null(start)) start <- min(obj[, time])
    ii <- which(obj[, time] == start)
    ii <- ii[order(unique(obj[, id]))][tapply(obj[, id], obj[, id])]
    obj[, x] / obj[ii, x]
}

这样:

> myFract(tab1)
[1] 1.0000000 0.9137056 0.8312183 1.0000000 0.9145963 0.8447205

答案 4 :(得分:0)

如果您可以安全地假设您的注意力不会随着时间的推移而增加,那么最短且最快的计算答案就是......

tab1$concp <- ave(tab1$conc, tab1$pat, FUN = function(x) x/max(x))