0

グループの現在のメンバーシップ ステータス、つまりメンバーの名前があるとします。さらに、新しいメンバーがグループに追加された、および/または古いメンバーがグループから削除された可能性がある時間に関するデータがあります.

当面のタスクは、これらすべての時点でグループのメンバーシップを再作成することです。私は周りを見回しましたが、この問題の解決策は見つかりませんでした。これを行うエレガントな方法を知っている人はいますか?

再現可能な例:

入力:

periods <- 5
indx <- paste0("t-", seq_len(periods))
[1] "t-1" "t-2" "t-3" "t-4" "t-5"

current <- letters[seq_len(10)]
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

incoming <- setNames(letters[seq_len(periods) + 5], indx)
incoming[2] <- NA
t-1 t-2 t-3 t-4 t-5
"f"  NA "h" "i" "j"

outgoing <- setNames(letters[seq_len(periods) + 10], indx)
outgoing[4] <- NA
t-1 t-2 t-3 t-4 t-5
"k" "l" "m"  NA "o"

出力:

$current
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

$`t-1`
 [1] "a" "b" "c" "d" "e" "g" "h" "i" "j" "k"

$`t-2`
 [1] "a" "b" "c" "d" "e" "g" "h" "i" "j" "k" "l"

$`t-3`
 [1] "a" "b" "c" "d" "e" "g" "i" "j" "k" "l" "m"

$`t-4`
 [1] "a" "b" "c" "d" "e" "g" "j" "k" "l" "m"

$`t-5`
 [1] "a" "b" "c" "d" "e" "g" "k" "l" "m" "o"

免責事項:私はこれに対する解決策を書きました。これを質問への回答として投稿します。その意図は、この問題と可能な解決策を文書化し、他の独創的なおよび/または既存の解決策または改善を引き出すことです。

4

1 に答える 1

0

関数create_mem_ts(メンバーシップ時系列)は、質問に投稿された目的の出力を生成します。

create_mem_ts <- function (ctime, added, removed, current) {

  # Create a time-series of membership of a set.

  # Inputs:

  ## ctime:     Time of changes in set.
  ##            An atomic vector of a time-series class or otherwise,
  ##
  ##            interpretable as a time-series in descending order (for e.g.
  ##            `t-1`, `t-2`, `t-3` etc.
  ##
  ##            Is an index of when the changes in membership happened in time.
  ##            Allows repeats but no NAs.

  ## added:     Member(s) added to the set.
  ##            An atomic vector or a list of the same length as ctime.
  ##
  ##            If an atomic vector, represents exactly one member added at
  ##            the corresponding ctime.
  ##
  ##            If a list, represents multiple members added at corresponding
  ##            ctime.

  ## removed:   Member(s) removed from the set.
  ##            An atomic vector or a list of the same length as ctime.
  ##
  ##            If an atomic vector, represents exactly one member removed at
  ##            the corresponding ctime.
  ##
  ##            If a list, represents multiple members removed at the
  ##            corresponding ctime.

  ## current:   Current membership of the set.
  ##            An atomic vector listing the current membership of the set.

  # Output:

  ## A list of the same length as ctime named by values in ctime (coerced to
  ## character by the appropriate method). 

  stopifnot(is.atomic(ctime),
            is.atomic(added) || is.list(added),
            is.atomic(removed) || is.list(removed))

  if (any(is.na(ctime))) stop("NAs not allowed in the ctime.")

  stopifnot(length(ctime) == length(added),
            length(added) == length(removed))

  if (any(duplicated(ctime))) {
    ctime.u <- unique(ctime)
    ctime.f <- factor(ctime, levels=as.character(ctime.u))
    added <- split(added, ctime.f)
    removed <- split(removed, ctime.f)
  } else {
    ctime.u <- ctime
  }

  out <- setNames(vector(mode="list", length=length(ctime.u) + 1),
                  c("current", as.character(ctime.u)))
  out[["current"]] <- current

  for (i in 2:length(out))
    out[[i]] <- union(setdiff(out[[i - 1]], added[[i - 1]]),
                      na.omit(removed[[i - 1]]))

  attr(out, "index") <- ctime.u

  out

}

さらに、ctimeが上記の関数の有効な時系列クラスである場合、その出力を使用して、この関数を使用して関数 (ctime の範囲内) を使用して任意のタイムスタンプのメンバーシップを生成できますmemship_at

memship_at <- function (mem_ts, at) {

  stopifnot(inherits(at, class(attr(mem_ts, "index"))))

  just.before <- which(at > attr(mem_ts, "index"))[1]

  if (just.before > 1)
    mem_ts[[just.before - 1]]
  else
    mem_ts[[1]]

}
于 2013-07-10T11:20:37.943 に答える