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 代表参与者所处的条件(例如,V1 下的 1 表示该参与者处于条件 1,V4 下的 1 表示该参与者处于条件 4)。旁注:数据不是对称的,因此有更多的参与者分布在 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
4

3 回答 3

2

我们可以在“数据”中的非 NA 元素的逻辑矩阵上使用max.colwith 。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 元素被索引替换。然后,使用pmaxwithna.rm=TRUE并获取每行的最大值。

 do.call(pmax, c(col(data)*data, na.rm=TRUE))
 #[1]  1 NA  3  4
于 2016-02-02T16:37:44.317 回答
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 变量与处理因子一起保留的优点;此外,如果您有响应测量,它也会出现在值列中。

编辑:

如果您想在任何情况下都包含主题,则可以显式重建该指示变量:

data$VNA <- ifelse(apply(is.na(data), 1, all), 1, NA)
于 2016-02-02T17:59:54.730 回答
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
于 2016-02-02T18:19:21.420 回答