2014-05-09 3 views
0

Учитывая следующий кадр данных:Replicate значение строки после фактора

df <- data.frame(patientID = rep(c(1:4), 3), 
       condition = c(rep("A", 4), rep("B",4), rep("C",4)), 
       weight = round(rnorm(12, 70, 7), 1), 
       height = round(c(rnorm(4, 170, 10), rep(0, 8)), 1)) 

> head(df) 
    patientID condition weight height 
1   1   A 71.43 168.5 
2   2   A 59.89 177.3 
3   3   A 72.15 163.4 
4   4   A 70.14 166.1 
5   1   B 66.21 0.0 
6   2   B 66.62 0.0 

Как я могу скопировать высоту для каждого пациента из состояния А в двух других условиях? Я пробовал использовать для циклов, data.table и dplyr без успеха.

Как я могу достичь этого, используя либо методы?

ответ

2

Если ваши данные, как это выглядит - отсортировано по condition, patientID и пациенты за состояние идентичны, то вы можете просто использовать рециркуляцию следующим образом:

require(data.table) 
setDT(df)[, height := height[condition == "A"]] 

Но я понимаю, что много ifs есть.


Таким образом, не предполагая ничего о данных, с одним исключением, что condition,patientID пары являются уникальными, вы можете сделать:

require(data.table) 
setDT(df)[, height := height[condition == "A"], by=patientID] 

Еще раз, это делает использование утилизации, но в пределах каждого группа - поскольку она не предполагает, что данные упорядочены.


Оба указанных выше методов на выборочных данных дают:

#  patientID condition weight height 
# 1:   1   A 73.3 169.5 
# 2:   2   A 76.3 173.4 
# 3:   3   A 63.6 145.5 
# 4:   4   A 56.2 164.7 
# 5:   1   B 67.7 169.5 
# 6:   2   B 77.3 173.4 
# 7:   3   B 76.8 145.5 
# 8:   4   B 70.9 164.7 
# 9:   1   C 76.6 169.5 
# 10:   2   C 73.0 173.4 
# 11:   3   C 66.7 145.5 
# 12:   4   C 71.6 164.7 

Та же идея может быть переведен на dplyr как хорошо, что я оставлю его вам попробовать. Подсказка: для этого требуется только group_by и mutate.

1

Нет необходимости в этом причудливом материале. Просто используйте оператор $ и [ подмножество.

> df$height <- df$height[df$patientID] 
> df 
    patientID condition weight height 
1   1   A 67.4 175.1 
2   2   A 66.8 179.0 
3   3   A 49.7 159.7 
4   4   A 64.5 165.3 
5   1   B 66.0 175.1 
6   2   B 70.8 179.0 
7   3   B 58.7 159.7 
8   4   B 74.3 165.3 
9   1   C 70.9 175.1 
10   2   C 75.6 179.0 
11   3   C 61.3 159.7 
12   4   C 74.5 165.3 
+0

Это не устойчиво к перестановкам строк, не так ли? 'DF <-df [образец (nrow (DF)),]; df $ height <- df $ height [df $ patientID] 'Итак, вы предполагаете, что все должно быть отсортировано? – MrFlick

+0

Мне кажется, что он уже отсортирован. –

+0

Согласен. Данные выборки сортируются. Я просто хотел пояснить, что это требование. Также это будет работать только для пациентов, которые начинаются с 1. Если вы добавили 10 к каждому идентификатору, у вас также возникнет проблема, если вы не преобразуете идентификатор пациента в фактор. – MrFlick

1

Это должно сделать трюк. Он предполагает, что первый уровень фактора условия всегда совпадает с истинными данными.

idx <- tapply(rownames(df), list(df$patientID, df$condition), identity) 
idx<-na.omit(cbind(as.vector(idx[,-1]),as.vector(idx[,1]))) 
df[as.vector(idx[,1]),"height"] <- df[as.vector(idx[,2]), "height"] 

И от @ предложения Аруна

df$height<-with(df, ave(ifelse(condition=="A",height,-1), 
    factor(patientID), FUN=max)) 

, где вы можете быть явным об уровне состояния вытащить значения из

+0

Хорошая точка @ Арун. Проблема с двойным столбцом преследовала меня. Я закончил использование 'ifelse', как указано выше. У вас была другая идея для использования 'ave'? – MrFlick

+0

@ Арун, я вижу. Это тоже очень хорошо. – MrFlick

+0

@arun Да. Если все отсутствующие значения равны 0 (или, по крайней мере, меньше А). Это будет нормально работать. Я просто хочу удостовериться, что вы перезаписали что-нибудь в условиях, отличных от A, на случай случайных других данных, как там. – MrFlick

Смежные вопросы