reduce row to unique items

安稳与你 提交于 2019-12-06 16:45:11

If your aim is to calculate the total number of each pathway

You could use something like this (using data.table because of the nice way it handles lists as elements within a data.table (data.frame-like) object.

I am using !duplicated(...) to remove the duplicates as this is slightly more efficient than unique.

library(data.table)
library(reshape2)
# make the rownames a column 
test$id <- rownames(test)
# put in long format
DT <- as.data.table(melt(test,id='id'))
# get the unique steps and concatenate into a unique identifier for each pathway
DL <- DT[!is.na(value), {.steps <- value[!duplicated(value)]
  stepid <- paste(.steps, sep ='.',collapse = '.')
  list(steps = list(.steps), stepid =stepid)}, by=id]
##    id                            steps                           stepid
## 1:  1           freshman,junior,senior           freshman.junior.senior
## 2:  2 freshman,junior,sophomore,senior freshman.junior.sophomore.senior
## 3:  3 freshman,junior,sophomore,senior freshman.junior.sophomore.senior
## 4:  4                 sophomore,senior                 sophomore.senior
## 5:  5                 sophomore,senior                 sophomore.senior
## 6:  6                           senior                           senior

# count the number per path

DL[, .N, by = stepid]
##                              stepid N
## 1:           freshman.junior.senior 1
## 2: freshman.junior.sophomore.senior 2
## 3:                 sophomore.senior 2
## 4:                           senior 1

lapply, when passed a data.frame, operates on its columns. That's because a data.frame is a list whose elements are the columns. Instead of lapply, you can use apply with MARGIN=1:

unique.padded <- function(x) {
   uniq <- unique(x)
   out  <- c(uniq, rep(NA, length(x) - length(uniq)))
}

t(apply(test, 1, unique.padded))

#   [,1]        [,2]     [,3]        [,4]    
# 1 "freshman"  "junior" "senior"    NA      
# 2 "freshman"  "junior" "sophomore" "senior"
# 3 "freshman"  "junior" "sophomore" "senior"
# 4 "sophomore" "senior" NA          NA      
# 5 "sophomore" "senior" NA          NA      
# 6 "senior"    NA       NA          NA

Edit: I saw your comment about your final goal. I would do something like this:

table(sapply(apply(test, 1, function(x)unique(na.omit(x))),
             paste, collapse = "_"))

#           freshman_junior_senior freshman_junior_sophomore_senior 
#                                1                                2 
#                           senior                 sophomore_senior 
#                                1                                2 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!