私は、要素の構造、サイズ、または順序が均一ではない(両方が存在する可能性があり、同一として扱われる必要がある)深くネストされたリストを含むリスト列を持つ大きな(数百万行)データテーブルを操作していlist(x=1,y=2)
ますlist(y=2,x=1)
。データテーブルの一部の列とリスト列のデータのサブセットを含む任意のグループ化を繰り返し実行する必要があります。すべての行にサブセットと一致する値があるわけではありません。
私が思いついたアプローチは非常に複雑に感じます。重要なポイントは次のとおりです。
ネストされたリスト構造の値を識別します。私のアプローチは、を使用することです。これは
ul <- unlist(list_col)
、ネストされたデータ構造を「フラット化」し、各要素に直接アクセスするための階層名を作成しますaddress.country.code
。リストされていない同じデータの順列がグループ化の観点から等しいと見なされるようにする。私のアプローチは、リストされていないベクトルをそれらの値の名前で並べ替え、
ul[order(names(ul))]
その結果を参照によって新しい文字ベクトル列として割り当てることです。フラット化された値のサブセットでグループ化を実行します。
by=
値がリストまたはベクトルである列を操作することはできませんでした。したがって、一意の文字ベクトルを単純な値にマップする方法を見つける必要がありました。私はこれをで行いましdigest
た。
2つの主力機能は次のとおりです。
# Flatten list column in a data.table
flatten_list_col <- function(dt, col_name, flattened_col_name='props') {
flatten_props <- function(d) {
if (length(d) > 0) {
ul <- unlist(d)
names <- names(ul)
if (length(names) > 0) {
ul[order(names)]
} else {
NA
}
} else {
NA
}
}
flattened <- lapply(dt[[col_name]], flatten_props)
dt[, as.character(flattened_col_name) := list(flattened), with=F]
}
# Group by properties in a flattened list column
group_props <- function(prop_group, prop_col_name='props') {
substitute({
l <- lapply(eval(as.name(prop_col_name)), function(x) x[names(x) %in% prop_group])
as.character(lapply(l, digest))
}, list(prop_group=prop_group, prop_col_name=prop_col_name))
}
再現可能な例を次に示します。
library(data.table)
dt <- data.table(
id=c(1,1,1,2,2,2),
count=c(1,1,2,2,3,3),
d=list(
list(x=1, y=2),
list(y=2, x=1),
list(x=1, y=2, z=3),
list(y=5, abc=list(a=1, b=2, c=3)),
NA,
NULL
)
)
flatten_list_col(dt, 'd')
dt[, list(total=sum(count)), by=list(id, eval(group_props(c('x', 'y'))))]
出力は次のとおりです。
> flatten_list_col(dt, 'd')
id count d props
1: 1 1 <list> 1,2
2: 1 1 <list> 1,2
3: 1 2 <list> 1,2,3
4: 2 2 <list> 1,2,3,5
5: 2 3 NA NA
6: 2 3 NA
> dt[, list(total=sum(count)), by=list(id, eval(group_props(c('x', 'y'))))]
id group_props total
1: 1 325c6bbb2c33456d0301cf3909dd1572 4
2: 2 7aa1e567cd0d6920848d331d3e49fb7e 2
3: 2 ee7aa3b9ffe6bffdee83b6ecda90faac 6
このアプローチは機能しますが、リストをフラット化して順序付けする必要があり、ダイジェストを計算する必要があるため、かなり非効率的です。私は次のことについて疑問に思っています:
これは、リスト列から直接値を取得することで、フラット化された列を作成せずに実行できますか?これには、単純な名前ではなく、選択したプロパティを式として指定する必要があります。
の必要性を回避する方法はあり
digest
ますか?