Найти переменные, которые встречаются только в одном кластере в data.frame в R - PullRequest
1 голос
/ 11 ноября 2019

Используя BASE R, мне интересно, как ответить на следующий вопрос:

Существуют ли какие-либо значения в X или Y (то есть, представляющие интерес переменные), которые встречаются только в одном элементе в m (как кластер) а не другие? Если да, выведите мой желаемый результат ниже.

Например: Здесь мы видим, что X == 3 происходит только в элементе m[[3]], но не m[[1]] и m[[2]]. Здесь мы также видим, что Y == 99 встречается только в m[[1]], но не в других.

Примечание: ниже приведен игрушечный пример, функциональный ответ приветствуется. И X & Y может быть или не быть числовым (например, быть строкой).

f <- data.frame(id = c(rep("AA",4), rep("BB",2), rep("CC",2)), X = c(1,1,1,1,1,1,3,3), 
            Y = c(99,99,99,99,6,6,6,6))

m <- split(f, f$id) # Here is `m`

mods <- names(f)[-1] # variables of interest names

Желаемый вывод:

list(AA = c(Y = 99), CC = c(X = 3))

# $AA
# Y 
# 99 

# $CC
# X 
# 3 

Ответы [ 3 ]

2 голосов
/ 11 ноября 2019

Это решение на основе rapply() и table().

ux <- rapply(m, unique)
tb <- table(uxm <- ux[gsub(rx <- "^.*\\.(.*)$", "\\1", names(ux)) %in% mods])
r <- Map(setNames, n <- uxm[uxm %in% names(tb)[tb == 1]], gsub(rx, "\\1", names(n)))
setNames(r, gsub("^(.*)\\..*$", "\\1", names(r)))
# $AA
# Y 
# 99 
# 
# $CC
# X 
# 3
1 голос
/ 11 ноября 2019

Здесь используется идея @ jay.sf о rapply() с идеей из предыдущего ответа :

vec <- rapply(lapply(m, '[', , mods), unique)
unique_vec <- vec[!duplicated(vec) & !duplicated(vec, fromLast = T)]

vec_names <- do.call(rbind, strsplit(names(unique_vec), '.', fixed = T))
names(unique_vec) <- vec_names[, 2]

split(unique_vec, vec_names[, 1])

$AA
 Y 
99 

$CC
X 
3 
1 голос
/ 11 ноября 2019
tmp = do.call(rbind, lapply(names(f)[-1], function(x){
    d = unique(f[c("id", x)])
    names(d) = c("id", "val")
    transform(d, nm = x)
}))

tmp = tmp[ave(as.numeric(as.factor(tmp$val)), tmp$val, FUN = length) == 1,]

lapply(split(tmp, tmp$id), function(a){
    setNames(a$val, a$nm)
})
#$AA
# Y 
#99 

#$BB
#named numeric(0)

#$CC
#X 
#3
...