複数の列の中央値を計算しようとしていますが、データが少しファンキーです。次の例のようになります。
_library(data.table)
dt <- data.table("ID" = c(1,2,3,4),"none" = c(0,5,5,3),
"ten" = c(3,2,5,4),"twenty" = c(0,2,3,1))
ID none ten twenty
1: 1 0 3 0
2: 2 5 2 2
3: 3 5 5 3
4: 4 3 4 1
_
表の列では、その値の出現回数を表します。発生の中央値を計算したいのですが。
たとえば、ID = 1の場合
_median(c(10, 10, 10))
_
作成したい計算です。
iD = 2の場合
_median(c(0, 0, 0, 0, 0, 10, 10, 20, 20))
_
私はrep()
とlapply()
を使用してみましたが、非常に限られた成功しか収めていません。私はrep()
のようなものについて理解しているので、繰り返すには値をハードコーディングする必要があります(たとえば、rep(0,2)
またはrep(10,2)
)。これは私が期待することです。私は、各列からの繰り返しでリストまたはベクトルを作成するのに苦労しています。
ここにもう一つありますdata.table
方法(一意のID
と仮定):
dt[, median(rep(c(0, 10, 20), c(none, ten, twenty))), by=ID]
# ID V1
# 1: 1 10
# 2: 2 0
# 3: 3 10
# 4: 4 10
これは、改造せずに@eddiの回答を得ようとする試みです(これは最後の手段として使用する傾向があります)。
列名を対応する数値に変換するための辞書が必要ですが、それはかなり簡単です。
dict = data.table(name = c('none', 'ten', 'twenty'), number = c(0, 10, 20))
melt(dt, id.var = 'ID')[
dict, on = c(variable = 'name')][, median(rep(number, value)), by = ID]
# ID V1
#1: 1 10
#2: 2 0
#3: 3 10
#4: 4 10
行単位の操作と再形成を回避する方法を次に示します。
_dt[, m := {
cSD = Reduce(`+`, .SD, accumulate=TRUE)
k = floor(cSD[[length(.SD)]]/2)
m = integer(.N)
for(i in seq_along(cSD)) {
left = m == 0L
if(!any(left)) break
m[left] = i * (cSD[[i]][left] >= k[left])
}
names(.SD)[m]
}, .SDcols=none:twenty]
_
与える
_ ID none ten twenty m
1: 1 0 3 0 ten
2: 2 5 2 2 none
3: 3 5 5 3 ten
4: 4 3 4 1 ten
_
ループでは、@ alexis_laz 'スタイルを使用しています。 https://stackoverflow.com/a/30513197/
列名の翻訳はスキップしましたが、それは非常に簡単です。最後にc(0,10,20)
の代わりにnames(.SD)
を使用できます。
rowwise
dplyr
の方法は次のとおりです。
dt %>% rowwise %>%
do(med = median(c(rep(0, .$none), rep(10, .$ten), rep(20, .$twenty)))) %>%
as.data.frame
med
1 10
2 0
3 10
4 10
@Arunの答えに触発され、これも機能しています:
dt %>% group_by(ID) %>%
summarise(med = median(rep(c(0, 10, 20), c(none, ten, twenty))))
Source: local data table [4 x 2]
ID med
(dbl) (dbl)
1 1 10
2 2 0
3 3 10
4 4 10