2010-08-23 7 views
0

у меня есть кадр R данные:Создать новый столбец в data.frame с использованием условий каждой строки

> 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 при t = 0 для каждый пациент. Как и многие другие вещи, я попытался:

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

Но я ясно мили с правильным кодом, что означает «конц где Т == 0 и погладить == погладить для этой конкретной строки»

Я уверен, что могу использовать цикл for или что-то в этом роде, но надеялся, что есть что-то проще?

Благодаря

ответ

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 
+0

Я думаю, что это неверно. Возьмите подмножество 'tab1' (например:' tab1 <-subset (tab1, t <10) 'и проверьте результаты. Проблема заключается в' tab1 $ pat == unique (tab1 $ pat) ',' == 'оператор репликации более короткий вектор, поэтому (например, наборы данных) вы сравниваете «1,1,1,2,2,2' с« 1,2,1,2,1,2 », поэтому он случайно работает. Но если у вас есть другой вектор, – Marek

+0

@Marek: Спасибо, что заметили, что Marek, я исправил код, теперь он должен работать. – nico

+0

Эта '% in%' часть всегда 'TRUE'. Я думаю' startConc <-tab1 [tab1 $ t == 0,] '(или' subset (tab1, t == 0) '). – Marek

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 
0

Если вы можете смело предположить, что ваша концентрация не поднимается с течением времени то самый короткий и быстрый расчетливый ответ на это ...

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

Это будет работать, только если' max (tab1 $ conc) 'встречается при t = 0. –

+0

Что можно было бы поменять с помощью' tab1 $ conc/ave (ifelse (tab1 $ t == 0, tab1 $ conc, -Inf), tab1 $ pat, FUN = function (x) max (x)) ' – Marek

2

С plyr:

library(plyr) 
ddply(tab1, "pat", transform, conct0 = conc/conc[t == 0]) 
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:

> 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 
Смежные вопросы