35

dataframe3 つの列の値を取り、3 つの値の最小差を計算する関数を適用したいと考えています。

#dataset
df <- data.frame(a= sample(1:100, 10),b = sample(1:100, 10),c= sample(1:100, 10))

#function
minimum_distance <- function(a,b,c)
{
  dist1 <- abs(a-b)
  dist2 <- abs(a-c)
  dist3 <- abs(b-c)
  return(min(dist1,dist2,dist3))
}

私は次のようなものを探しています:

df$distance <- sapply(df, function(x) minimum_distance(x$a,x$b,x$c) )
## errormessage
Error in x$a : $ operator is invalid for atomic vectors

私はddplyを使用できますが:

df2 <- ddply(df,.(a),function(r) {data.frame(min_distance=minimum_distance(r$a,r$b, r$c))}, .drop=FALSE)

これはすべての列を保持するわけではありません。助言がありますか?

編集:私は最終的に使用しました:

df$distance <- mapply(minimum_distance, df$a, df$b, df$c)
4

4 に答える 4

57

mapply() を試してください:

qq <- mapply(minimum_distance, df$a, df$b, df$c)
于 2012-04-09T19:02:59.773 に答える
6

これを試して:

do.call("mapply", c(list(minimum_distance), df))

しかし、ベクトル化されたバージョンを書くことができます:

pminimum_distance <- function(a,b,c)
{
 dist1 <- abs(a-b)
 dist2 <- abs(a-c)
 dist3 <- abs(b-c)
 return(pmin(dist1,dist2,dist3))
}
pminimum_distance(df$a, df$b, df$c)

# or
do.call("pminimum_distance", df)
于 2012-04-09T19:06:28.860 に答える
5

私はこれが答えられたことを知っていますが、実際には、任意の数の列を取り、外部アプローチを使用してより一般化できる別のアプローチを採用します。

vdiff <- function(x){
    y <- outer(x, x, "-")
    min(abs(y[lower.tri(y)]))
}

apply(df, 1, vdiff)

これは少しきれいで柔軟だと思います。

編集:ザックのコメントごとに、非数値列を含むデータフレームでも機能するこのより形式化された関数を提案します。これは、それらを削除して数値列のみに作用します。

cdif <- function(dataframe){
    df <- dataframe[, sapply(dataframe, is.numeric)]
    vdiff <- function(x){
        y <- outer(x, x, "-")
        min(abs(y[lower.tri(y)]))
    }
    return(apply(df, 1, vdiff))
}

#TEST it out
set.seed(10)
(df <- data.frame(a = sample(1:100, 10), b = sample(1:100, 10), 
    c = sample(1:100, 10), d =  LETTERS[1:10]))

cdif(df)
于 2012-04-09T21:37:17.910 に答える
2

関数を記述してから、ベクターに対して mapply を使用することをお勧めします。

 f1 <- function(a,b,c){
 d =abs(a-b)
 e =abs(b-c)
 f= abs(c-a)
 return(pmin(d,e,f))
 }

 qq <- mapply(f1, df$a, df$b, df$c)
于 2016-07-28T04:38:29.343 に答える