2

データフレームから列を選択して、結果の連続した列シーケンスができるだけ長くなるようにしますが、後で削除する必要があるため、NA を持つ行の数はできるだけ少なくします。

(私がこれをやりたい理由は、(遷移TraMineR::seqsubm()確率によって) 遷移コストのマトリックスを自動的に取得するために実行し、後でそれを実行したいcluster::agnes()からです。意味深。)TraMineR::seqsubm()NAcluster::agnes()NA

その目的のために、可能なすべてのパワーサブセットを原理的に計算し、s をチェックする作業関数NAを既に作成しました。dこれは、10x5 行列を表す次のおもちゃのデータでうまく機能します。

> d
   id X1 X2 X3 X4 X5
1   A  1 11 21 31 41
2   B  2 12 22 32 42
3   C  3 13 23 33 NA
4   D  4 14 24 34 NA
5   E  5 15 25 NA NA
6   F  6 16 26 NA NA
7   G  7 17 NA NA NA
8   H  8 18 NA NA NA
9   I  9 NA NA NA NA
10  J 10 NA NA NA NA
11  K NA NA NA NA NA

ここでの問題は、 34235 x 17 のマトリックスを表す調査データにアルゴリズムを実際に適用したいということです!

私のコードは Code Review でレビューされましたが、まだ実際のデータに適用できません。

このアプローチでは膨大な計算になることは承知しています。(おそらく、スーパーコンピューター以外には大きすぎる?!)

より適切なアプローチを知っている人はいますか?

Code Review の@minem によって既に強化された関数を紹介します。

seqRank2 <- function(d, id = "id") {
  require(matrixStats)

  # change structure, convert to matrix
  ii <- as.character(d[, id])
  dm <- d
  dm[[id]] <- NULL
  dm <- as.matrix(dm)
  rownames(dm) <- ii

  your.powerset = function(s){
    l = vector(mode = "list", length = 2^length(s))
    l[[1]] = numeric()
    counter = 1L
    for (x in 1L:length(s)) {
      for (subset in 1L:counter) {
        counter = counter + 1L
        l[[counter]] = c(l[[subset]], s[x])
      }
    }
    return(l[-1])
  }

  psr <- your.powerset(ii)
  psc <- your.powerset(colnames(dm))

  sss <- lapply(psr, function(x) {
    i <- ii %in% x
    lapply(psc, function(y) dm[i, y, drop =  F])
    })

  cn <- sapply(sss, function(x)
    lapply(x, function(y) {

      if (ncol(y) == 1) {
        if (any(is.na(y))) return(NULL)
          return(y)
        }

      isna2 <- matrixStats::colAnyNAs(y)
      if (all(isna2)) return(NULL)
      if (sum(isna2) == 0) return(NA)
      r <- y[, !isna2, drop = F]
      return(r)
      }))

  scr <- sapply(cn, nrow)
  scc <- sapply(cn, ncol)

  namesCN <- sapply(cn, function(x) paste0(colnames(x), collapse = ", "))
  names(scr) <- namesCN
  scr <- unlist(scr)

  names(scc) <- namesCN
  scc <- unlist(scc)

  m <- t(rbind(n.obs = scr, sq.len = scc))
  ag <- aggregate(m, by = list(sequence = rownames(m)), max)
  ag <- ag[order(-ag$sq.len, -ag$n.obs), ]
  rownames(ag) <- NULL
  return(ag)
}

収量:

> seqRank2(d)
         sequence n.obs sq.len
1  X1, X2, X3, X4     4      4
2      X1, X2, X3     6      3
3      X1, X2, X4     4      3
4      X1, X3, X4     4      3
5      X2, X3, X4     4      3
6          X1, X2     8      2
7          X1, X3     6      2
8          X2, X3     6      2
9          X1, X4     4      2
10         X2, X4     4      2
11         X3, X4     4      2
12             X1    10      1
13             X2     8      1
14             X3     6      1
15             X4     4      1
16             X5     2      1

> system.time(x <- seqRank2(d))
   user  system elapsed 
   1.93    0.14    2.93 

この場合、またはそれらが連続的であり、適切な数の観測値が得られるためX1, X2, X3, X4X1, X2, X3またはを選択します。X2, X3, X4

期待される出力:

したがって、おもちゃのデータdの場合、予想される出力は次のようになります。

> seqRank2(d)
sequence n.obs sq.len
1  X1, X2, X3, X4     4      4
2      X1, X2, X3     6      3
3      X2, X3, X4     4      3
4          X1, X2     8      2
5          X2, X3     6      2
6          X3, X4     4      2
7              X1    10      1
8              X2     8      1
9              X3     6      1
10             X4     4      1
11             X5     2      1

そして最後に、関数は巨大な行列d.hugeで適切に実行され、現時点でエラーが発生するはずです:

> seqRank2(d.huge)
Error in vector(mode = "list", length = 2^length(s)) : 
  vector size cannot be infinite

玩具データd

d <- structure(list(id = structure(1:11, .Label = c("A", "B", "C", 
"D", "E", "F", "G", "H", "I", "J", "K"), class = "factor"), X1 = c(1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, NA), X2 = c(11L, 12L, 13L, 
14L, 15L, 16L, 17L, 18L, NA, NA, NA), X3 = c(21L, 22L, 23L, 24L, 
25L, 26L, NA, NA, NA, NA, NA), X4 = c(31L, 32L, 33L, 34L, NA, 
NA, NA, NA, NA, NA, NA), X5 = c(41L, 42L, NA, NA, NA, NA, NA, 
NA, NA, NA, NA)), row.names = c(NA, -11L), class = "data.frame")

玩具データd.huge

d.huge <- setNames(data.frame(matrix(1:15.3e5, 3e4, 51)), 
                   c("id", paste0("X", 1:50)))
d.huge[, 41:51] <- lapply(d.huge[, 41:51], function(x){
  x[which(x %in% sample(x, .05*length(x)))] <- NA
  x
})

付録(コメントの最新の回答を参照):

d.huge <- read.csv("d.huge.csv")
d.huge.1 <- d.huge[sample(nrow(d.huge), 3/4*nrow(d.huge)), ]
d1 <- seqRank3(d.huge.1, 1.27e-1, 1.780e1)
d2 <- d1[complete.cases(d1), ]
dim(d2)
names(d2)
4

3 に答える 3

1

明確にするために、seqsubm関数 fromTraMineRは NA や異なる長さのシーケンスではまったく問題ありません。ただし、この関数は状態シーケンス オブジェクト ( で作成されるseqdef) を入力として想定しています。

この関数seqsubmは、異なる方法を使用して状態間の代替コスト (つまり、非類似度) を計算するためのものです。おそらく、観測された遷移確率からコストを導出するメソッド ( 'TRATE')、つまり 2- p(i|j) - p(j|i)を参照していると思われます。ここで、p(i|j)は状態にある確率です。i in tは、状態j in t -1 にあったときです。したがって、必要なのは遷移確率だけです。これは、さまざまな長さのシーケンスのセットから、またはそれらの中にギャップがあるシーケンスから簡単に推定できます。

ex1に付属のデータを使用して以下に説明しますTraMineR。(おもちゃの例ではさまざまな状態が多数あるため、結果として得られる代替コストのマトリックスは、この図では大きすぎます (28 x 28)。)

library(TraMineR)
data(ex1)
sum(is.na(ex1))

# [1] 38

sq <- seqdef(ex1[1:13])
sq

#    Sequence                 
# s1 *-*-*-A-A-A-A-A-A-A-A-A-A
# s2 D-D-D-B-B-B-B-B-B-B      
# s3 *-D-D-D-D-D-D-D-D-D-D    
# s4 A-A-*-*-B-B-B-B-D-D      
# s5 A-*-A-A-A-A-*-A-A-A      
# s6 *-*-*-C-C-C-C-C-C-C      
# s7 *-*-*-*-*-*-*-*-*-*-*-*-*

sm <- seqsubm(sq, method='TRATE')
round(sm,digits=3)

#      A-> B->   C-> D->
# A->   0 2.000   2 2.000
# B->   2 0.000   2 1.823
# C->   2 2.000   0 2.000
# D->   2 1.823   2 0.000

さて、あなたが州の非類似性で何をしたいのか、私には明らかではありません。それらをクラスタリング アルゴリズムに入力すると、状態がクラスター化されます。シーケンスをクラスタ化する場合は、最初にシーケンス間の非類似度を計算し (引数としてseqdist返された置換コストの行列を使用し、場合によってはこれを渡します)、結果の距離行列をクラスタリング アルゴリズムに入力する必要があります。 seqsubmsm

于 2018-12-08T09:09:37.300 に答える
1

行列に変換し、各列の Na カウントを計算します。

dm <- is.na(d[, -1])
na_counts <- colSums(dm)
x <- data.frame(na_counts = na_counts, non_na_count = nrow(dm) - na_counts)
x <- as.matrix(x)

# create all combinations for column indexes:
nx <- 1:nrow(x)
psr <- do.call(c, lapply(seq_along(nx), combn, x = nx, simplify = FALSE))
# test if continuous:
good <- sapply(psr, function(y) !any(diff(sort.int(y)) != 1L))
psr <- psr[good == T] # remove non continuous
# for each combo count nas and non NA:
s <- sapply(psr, function(y) colSums(x[y, , drop = F]))

# put all together in table:
res <- data.frame(var_count = lengths(psr), t(s))
res$var_indexes <- sapply(psr, paste, collapse = ',')
res
#    var_count na_counts non_na_count var_indexes
# 1          1         1           10           1
# 2          1         3            8           2
# 3          1         5            6           3
# 4          1         7            4           4
# 5          1         9            2           5
# 6          2         4           18         1,2
# 7          2         8           14         2,3
# 8          2        12           10         3,4
# 9          2        16            6         4,5
# 10         3         9           24       1,2,3
# 11         3        15           18       2,3,4
# 12         3        21           12       3,4,5
# 13         4        16           28     1,2,3,4
# 14         4        24           20     2,3,4,5
# 15         5        25           30   1,2,3,4,5

# choose

var インデックスはソートされているため、速度を上げるために次のように簡単に使用できます。

good <- sapply(psr, function(y) !any(diff(y) != 1L))
于 2018-12-04T14:31:59.667 に答える