2016-02-02 6 views
1

я часто сталкиваются данными, которые выглядят так:уникальных значений строк

#create dummy data frame 
data <- as.data.frame(diag(4)) 
data[data==0] <- NA 
data[2,2] <- NA 
data 

#V1 V2 V3 V4 
#1 1 NA NA NA 
#2 NA NA NA NA 
#3 NA NA 1 NA 
#4 NA NA NA 1 

Ряды представляют участник и столбцы V1 через V4 представляют собой условие, что участник находится в (например, 1 под V1 означает, что этот участник в условии 1, a 1 под V4 означает, что этот участник находится в состоянии 4). Sidenote: данные не являются симметричными, поэтому в течение 4-х условий намного больше участников.

То, что я хочу, это вектор с условием для каждого участника:

1 NA 3 4 

Я написал следующий немного, но было интересно, если есть более эффективный способ (то есть, используя меньше строк кода)?

#replace entries with condition numbers 
cond <- data + matrix(rep(0:3, 4), 4, byrow=TRUE) #add 0 to 1 for condition 1... 

#get all unique elements (ignore NAs) 
cond <- apply(cond, 1, function(x)unique(x[!is.na(x)])) 

#because I ignored NAs just now, cond[2,2] is numeric(0) 
#assign NA to all values that are numeric(0) 
cond[sapply(cond, function(x) length(x)==0)] <- NA 

cond <- unlist(cond) 
cond 
#[1] 1 NA 3 4 

ответ

2

Мы можем использовать max.col с ties.method='first' на логической матрице элементов без НС в «данные». Чтобы строки, которые имеют только элементы NA, как NA, умножаем индекс max.col на rowSums логической матрицы с 0 строками не-NA, преобразованными в NA (NA^).

max.col(!is.na(data), 'first')* NA^!rowSums(!is.na(data)) 
#[1] 1 NA 3 4 

Или другой вариант: pmax. Мы умножаем индекс столбца на данные таким образом, чтобы элементы не-NA заменялись индексом. Затем используйте pmax с na.rm=TRUE и получите максимальное значение за каждую строку.

do.call(pmax, c(col(data)*data, na.rm=TRUE)) 
#[1] 1 NA 3 4 
1

Использование reshape2 пакет:

> data$ID <- rownames(data) 
> melt(data, 'ID', na.rm=TRUE) 
    ID variable value 
1 1  V1  1 
11 3  V3  1 
16 4  V4  1 

ИМХО, это имеет то преимущество, сохраняя переменную ID наряду с фактором лечения; также, если у вас есть измерение ответа, оно также входит в столбец значений.

EDIT:

Если вы хотите включить эту тему ни при каких условиях, вы можете восстановить эту индикаторную переменную в явном виде:

data$VNA <- ifelse(apply(is.na(data), 1, all), 1, NA) 
1

Менее умный и эффективный, чем другие решения, но, возможно, более удобным для чтения?

apply(data, 
     MARGIN = 1, 
     FUN = function(x) { 
      if(all(is.na(x))) return(NA) 
      return(which(!is.na(x))) 
     } 
) 
# [1] 1 NA 3 4 
Смежные вопросы