任意の長さの列名のリストに基づいて動的サブセットを取得する関数を実装しようとしています
静的コードは次のとおりです。
s <- c("s0","s1","s2")
d.subset <- d[ d$s0 > 0 | d$s1 > 0 | d$s2 > 0,]
d$s0 > 0 | d$s1 > 0 | d$s2 > 0
ただし、 sに基づいてパーツを生成したいと思います。as.formula()を生成してみましたが、「無効な数式」エラーが発生しました。
データフレームの例:
d <- data.frame(s0 = c(0,1,0,0), s1 = c(1,1,1,0), s2 = c(0,1,1,0))
s <- c("s0","s1","s2")
これが簡単な解決策rowSums
です:
d[as.logical(rowSums(d[s] > 0)), ]
結果:
s0 s1 s2
1 0 1 0
2 1 1 1
3 0 1 1
あなたのコードは再現性$
がないので、これはあなたが望むものでの暗闇の中でのショットです。演算子ではなくインデックスを使用したいと思います。
s <- c("s0","s1","s2")
d.subset <- d[ d[, s[1]] > 0 | d[, s[2]] > 0 | d[, s[3]] > 0,]
@ sven-hohensteinからの回答に触発されて、フォームで指定された述語のリストに基づいてフィルタリングする一般化された関数がありますcolumn=list(binary_operator, rhs)
(例:) 。x=list(`<=`, 3)
x <= 3
#' Filter a data frame dynamically
#'
#' @param df data frame to filter
#' @param controls list of filters (with optional operators)
filter_data = function(df, controls) {
evaluate = function(predicate, value) {
if (is.list(predicate)) {
operator = predicate[[1L]]
rhs = predicate[[2L]]
} else {
operator = `==`
rhs = predicate
}
return(operator(value, rhs))
}
index = apply(
mapply(evaluate, predicate=controls, value=df[names(controls)]), 1L, all
)
return(df[index, ])
}
フィルタリング関数を使用して条件を適用する例を次に示しますx == 2 & y <= 2.5 & z != 'C'
。
# create example data
df = data.frame(
x=sample(1:3, 100L, TRUE),
y=runif(100L, 1, 5),
z=sample(c('A', 'B', 'C'), 100L, TRUE)
)
controls = list(x=2L, y=list(`<=`, 2.5), z=list(`!=`, 'C'))
filter_data(df, controls)
(編集:このソリューションは強くお勧めしません。詳細については、コメントとこのStack Overflowの質問を参照してください。)
私はこのトリックを学びました。すべてを文字列として記述し、を使用しますeval(parse(text=
。この例ではおそらく最良の方法ではありませんが、より一般的に使用できます。
s <- c("s0","s1","s2")
s.1 <- paste0("d$",s," > 0",collapse=" | ")
d.subset <- eval(parse(text=paste0("d[",s.1,",]")))