Purrr :: mapを使用して行ごとの反復を実現するにはどうすればよいですか?
標準的な行単位の適用でこれを行う方法は次のとおりです。
df <- data.frame(a = 1:10, b = 11:20, c = 21:30)
lst_result <- apply(df, 1, function(x){
var1 <- (x[['a']] + x[['b']])
var2 <- x[['c']]/2
return(data.frame(var1 = var1, var2 = var2))
})
しかし、これはあまりにもエレガントではなく、私はむしろpurrrでやりたいです。より速くなる場合もあれば、そうでない場合もあります。
行ごとの反復にはpmap
を使用できます。列は、使用している関数の引数として使用されます。この例では、引数が3つの関数を使用します。
たとえば、あなたがしている作業に匿名関数を使用しているpmap
は次のとおりです。列は、データセットにある順序で関数に渡されます。
pmap(df, function(a, b, c) {
data.frame(var1 = a + b,
var2 = c/2)
} )
purrrチルダ「ショートハンド」を使用して、2つのドットが前に付いた数字で順番に列を参照することにより、匿名関数を使用できます。
pmap(df, ~data.frame(var1 = ..1 + ..2,
var2 = ..3/2) )
これらの特定の結果をリストではなくdata.frameとして取得する場合は、pmap_dfr
を使用できます。
あなたの例ではベクトル化された操作のみを使用していることに注意してください。
_df %>% dplyr::transmute(var1 = a+b,var2 = c/2)
_
(またはベースR:transform(df,var1 = a+b,var2 = c/2)[4:5]
)
中央値などの非ベクトル化関数を使用する場合は、@ aosmithの答えのようにpmap
を使用するか、_dplyr::rowwise
_を使用できます。
rowwise
は低速であり、パッケージメンテナは代わりにmap
ファミリを使用することを推奨しますが、場合によってはpmap
よりも間違いなく簡単です。私は個人的には速度が問題にならないときにそれをまだ使用しています:
_library(dplyr)
df %>% transmute(var3 = pmap(.,~median(c(..1,..2,..3))))
df %>% rowwise %>% transmute(var3 = median(c(a,b,c)))
_
(厳密な名前のないリスト出力に戻るには、res %>% split(seq(nrow(.))) %>% unname
)
「好きな」関数のラッパーをいつでも自由に作成できます。
rmap <- function (.x, .f, ...) {
if(is.null(dim(.x))) stop("dim(X) must have a positive length")
.x <- t(.x) %>% as.data.frame(.,stringsAsFactors=F)
purrr::map(.x=.x,.f=.f,...)
}
新しい関数rmap
を適用する(r owwise map)
rmap(df1,~{
var1 <- (.x[[1]] + .x[[2]])
var2 <- .x[[3]]/2
return(data.frame(var1 = var1, var2 = var2))
})
追加情報:(上から下に評価)
df1 <- data.frame(a=1:3,b=1:3,c=1:3)
m <- matrix(1:9,ncol=3)
apply(df1,1,sum)
rmap(df1,sum)
apply(m,1,sum)
rmap(m,sum)
apply(1:10,1,sum) # intentionally throws an error
rmap(1:10,sum) # intentionally throws an error