3

縦断的なデータ セットletter内の最後のものを特定しようとしています。ID

私のデータがこのように見えるとしましょう。

dfL <- data.frame(ID = c(1L, 1L, 1L, 4L, 4L, 4L, 4L, 4L, 9L, 9L, 9L, 9L, 9L, 10L), week = c("BS", 4L, 6L, "BS", 6L, 9L, 9L, 12L, "BS", 4L, 6L, 9L, 12L, "BS"), outcome = c(14L, 28L, 42L, 14L, 46L, 64L, 71L, 85L, 14L, 28L, 51L, 66L, 84L, 0L), letter = c("a", "b", "a", "b", "a", "b", "a", "b", "a", "b", "a", "b", NA, NA)); dfL

それぞれIDに s 文字列 (aおよびb's) があり、その中の最後の文字を見つけてベースラインに配置する必要がIDあります

   ID week outcome letter
1   1   BS      14      a
2   1    4      28      b
3   1    6      42      a
4   4   BS      14      b
5   4    6      46      a
6   4    9      64      b
7   4    9      71      a
8   4   12      85      b
9   9   BS      14      a
10  9    4      28      b
11  9    6      51      a
12  9    9      66      b
13  9   12      84   <NA>
14 10   BS       0   <NA>

最終的な結果は次のようになると思いますが、

   ID week outcome letter last_letter
1   1   BS      14      a      a
2   1    4      28      b   <NA>
3   1    6      42      a   <NA>
4   4   BS      14      b      b
5   4    6      46      a   <NA>   
6   4    9      64      b   <NA>
7   4    9      71      a   <NA>
8   4   12      85      b   <NA>
9   9   BS      14      a      b
10  9    4      28      b   <NA>
11  9    6      51      a   <NA>
12  9    9      66      b   <NA>
13  9   12      84   <NA>   <NA>
14 10   BS       0   <NA>   <NA>

パッケージwhich.maxからと をいじりましたが、まだちょっと行き詰まっています。data.tableave

4

3 に答える 3

4

ベース R を使用aveして、次のようなカスタム関数でアプローチします。

FUN <- function(x) {
    if (all(is.na(x))) return(NA)
    tail(na.omit(x), 1)
}

dfL$lastL <- with(dfL, ave(letter, ID, FUN=FUN))

##    ID week outcome letter lastL
## 1   1   BS      14      a     a
## 2   1    4      28      b     a
## 3   1    6      42      a     a
## 4   4   BS      14      b     b
## 5   4    6      46      a     b
## 6   4    9      64      b     b
## 7   4    9      71      a     b
## 8   4   12      85      b     b
## 9   9   BS      14      a     b
## 10  9    4      28      b     b
## 11  9    6      51      a     b
## 12  9    9      66      b     b
## 13  9   12      84   <NA>     b
## 14 10   BS       0   <NA>  <NA>

編集:

自分のもののように見せたい場合は<NA>、このアプローチtapplyが機能します。

FUN <- function(x) {
    if (all(is.na(x))) {
        first <- NA
    } else {
        first <- tail(na.omit(x), 1)
    }
    out <- as.character(rep(NA, length(x)))
    out[1] <- as.character(first)
    out
}

dfL$lastL <- factor(unlist(with(dfL, tapply(letter, ID, FUN=FUN))))

##    ID week outcome letter lastL
## 1   1   BS      14      a     a
## 2   1    4      28      b  <NA>
## 3   1    6      42      a  <NA>
## 4   4   BS      14      b     b
## 5   4    6      46      a  <NA>
## 6   4    9      64      b  <NA>
## 7   4    9      71      a  <NA>
## 8   4   12      85      b  <NA>
## 9   9   BS      14      a     b
## 10  9    4      28      b  <NA>
## 11  9    6      51      a  <NA>
## 12  9    9      66      b  <NA>
## 13  9   12      84   <NA>  <NA>
## 14 10   BS       0   <NA>  <NA>
于 2013-03-27T18:58:19.700 に答える
2

あなたの質問が正しかったことを願っています (各 ID の最後の文字が何であるかはよくわかりません。それが最も高い結果をもたらすものだと思います):

ここにdata.table解決策があります:

library(data.table)
dfL <- as.data.table(dfL)
setkey(dfL, ID, outcome)
intDT <- dfL[!is.na(letter), list(lastL = tail(letter, 1)), by=ID]
setkey(intDT, ID)
intDT[dfL]
    ID lastL week outcome letter
 1:  1     a   BS      14      a
 2:  1     a    4      28      b
 3:  1     a    6      42      a
 4:  4     b   BS      14      b
 5:  4     b    6      46      a
 6:  4     b    9      64      b
 7:  4     b    9      71      a
 8:  4     b   12      85      b
 9:  9     b   BS      14      a
10:  9     b    4      28      b
11:  9     b    6      51      a
12:  9     b    9      66      b
13:  9     b   12      84     NA
14: 10    NA   BS       0     NA

ここで行っていることの簡単な説明:dfL最初にソートし、次に各 ID ( by=ID) の最後の値を取得しますletter(これは function で行われますtail)。その後、2 つの data.tables を再度マージする必要があります。

さらに簡単 (ルチアーノのコメントのおかげ):

dfL[!is.na(letter), lastL := tail(as.character(letter), 1), by=ID]
    ID week outcome letter lastL
 1:  1   BS      14      a     a
 2:  1    4      28      b     a
 3:  1    6      42      a     a
 4:  4   BS      14      b     b
 5:  4    6      46      a     b
 6:  4    9      64      b     b
 7:  4    9      71      a     b
 8:  4   12      85      b     b
 9:  9   BS      14      a     b
10:  9    4      28      b     b
11:  9    6      51      a     b
12:  9    9      66      b     b
13:  9   12      84     NA    NA
14: 10   BS       0     NA    NA

ここでは、すべて 1 ステップで完了します。letterただし、これは、列を文字に変換する場合にのみ機能します。

于 2013-03-27T18:54:19.883 に答える
2

これは plyr を使用したアプローチです。最初に NA を省略し、id で分割して、最後の値を調べます。その後、マージして戻します。

library(plyr)

last_letter <- ddply(na.omit(dfL), .(ID), function(x) tail(as.character(x$letter),1))
last_letter$week <- "BS"
names(last_letter)[2] <- "last_letter"
merge(dfL, last_letter, by = c("ID", "week"), all=TRUE)

   ID week outcome letter last_letter
1   1    4      28      b        <NA>
2   1    6      42      a        <NA>
3   1   BS      14      a           a
4   4   12      85      b        <NA>
5   4    6      46      a        <NA>
6   4    9      64      b        <NA>
7   4    9      71      a        <NA>
8   4   BS      14      b           b
9   9   12      84   <NA>        <NA>
10  9    4      28      b        <NA>
11  9    6      51      a        <NA>
12  9    9      66      b        <NA>
13  9   BS      14      a           b
14 10   BS       0   <NA>        <NA>
于 2013-03-27T18:59:07.370 に答える