2016-04-26 4 views
2

У меня есть dataframe, как показано ниже:Функция для повторяющихся строк

> df 
    pat_id disease 
[1,] "pat1" "dis1" 
[2,] "pat1" "dis1" 
[3,] "pat2" "dis0" 
[4,] "pat2" "dis5" 
[5,] "pat3" "dis2" 
[6,] "pat3" "dis2" 

Как я могу написать функцию, чтобы получить третью переменную, которая указывает на то же pat_id переменная заболевание представляет собой то же самое или нет, как показано ниже?

> df 
    pat_id disease var3 
[1,] "pat1" "dis1" "1" 
[2,] "pat1" "dis1" "1" 
[3,] "pat2" "dis0" "0" 
[4,] "pat2" "dis5" "0" 
[5,] "pat3" "dis2" "1" 
[6,] "pat3" "dis2" "1" 
+0

'as.integer (дублируется (dat) | duplicated (dat, fromLast = TRUE)) 'может работать, – user20650

+3

У вас нет данных. Это была матрица. –

ответ

5

Попробуйте ave() для групп, и завернуть результат от any(duplicated()) с as.integer(). Затем свяжите с cbind(). Хотя я мог бы порекомендовать вам использовать фрейм данных вместо матрицы.

cbind(
    df, 
    var3 = ave(df[,2], df[,1], FUN = function(x) as.integer(any(duplicated(x))) 
) 
#  pat_id disease var3 
# [1,] "pat1" "dis1" "1" 
# [2,] "pat1" "dis1" "1" 
# [3,] "pat2" "dis0" "0" 
# [4,] "pat2" "dis5" "0" 
# [5,] "pat3" "dis2" "1" 
# [6,] "pat3" "dis2" "1" 

Для больших данных я бы рекомендовал преобразовать в таблицу данных. Синтаксис на самом деле немного лучше, и, скорее всего, он будет быстрее.

library(data.table) 
dt <- as.data.table(df) 
dt[, var3 := if(any(duplicated(disease))) 1 else 0, by = pat_id] 

который дает

pat_id disease var3 
1: pat1 dis1 1 
2: pat1 dis1 1 
3: pat2 dis0 0 
4: pat2 dis5 0 
5: pat3 dis2 1 
6: pat3 dis2 1 

где классы столбцов будут более подходящими (символ, символ, целым). Или вы можете использовать as.integer(any(duplicated(disease))) вместо if/else.

+1

Кроме того, 'as.integer (ave (df [," disease "], df [," pat_id "], FUN = anyDuplicated)> 0)' как вариация темы, – thelatemail

+0

У меня также есть тройные строки pat_id, как Могу ли я изменить синтаксис? – trillian

+0

Как я могу изменить его, чтобы показать, является ли заболевание одинаковым для 3 или более строк с одним и тем же pat_id? – trillian

0

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

> df <- data.frame(pat_id=c("pat1","pat1", "pat2", "pat2", "pat3", "pat3"), 
+     disease=c("dis1","dis1","dis0","dis5","dis2","dis2"), 
+     stringsAsFactors = F) 
> counts<-apply(table(df), 1, function(x) sum(x!=0)) 
> df2<-data.frame(pat_id=names(counts), all_the_same=(counts==1)) 
> df3<-merge(df,df2) 
> df3 
    pat_id disease all_the_same 
1 pat1 dis1   TRUE 
2 pat1 dis1   TRUE 
3 pat2 dis0  FALSE 
4 pat2 dis5  FALSE 
5 pat3 dis2   TRUE 
6 pat3 dis2   TRUE 
> sapply(df3, class) 
     pat_id  disease all_the_same 
"character" "character" "logical" 

Это не важно, сколько из каждой комбинации вы должны и должны оставить свои строки как строки - не факторы.

Имея новый столбец в качестве логического позволяет легко делать такие запросы, как поиск всех пациентов, для которых он является истинным

> unique(df3$pat_id[df3$all_the_same]) 
[1] "pat1" "pat3" 
0

Один из вариантов использования dplyr

library(dplyr) 
as.data.frame(df) %>% 
    group_by(pat_id) %>% 
    mutate(var3 = as.integer(n_distinct(disease)==1)) 
# pat_id disease var3 
# (chr) (chr) (int) 
#1 pat1 dis1  1 
#2 pat1 dis1  1 
#3 pat2 dis0  0 
#4 pat2 dis5  0 
#5 pat3 dis2  1 
#6 pat3 dis2  1 
Смежные вопросы