R 将多列用作sapply的变量

R 将多列用作sapply的变量,r,dataframe,apply,R,Dataframe,Apply,我有一个dataframe,我想应用一个函数,获取三列的值并计算三个值之间的最小差值 #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 <- a

我有一个
dataframe
,我想应用一个函数,获取三列的值并计算三个值之间的最小差值

#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试试mapply():

qq试试这个:

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)

pminium_distance我知道这一点已经得到了回答,但实际上我会采用一种不同的方法,它可以容纳任意数量的列,并且使用外部方法更具概括性:

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

apply(df, 1, vdiff)

vdiff最好编写一个函数,然后在向量上使用mappy:

 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)

f1这很聪明,但不那么直截了当。好主意。然而,我的真实数据框不是矩阵-是否可以修改它以用于具有文本列的数据框?类似于outer(x,x,“-”,drop_string=T)?函数
outer
并不一定意味着您正在处理矩阵。它只需要两个向量和一个函数,并为这两个向量的所有可能组合生成一个矩阵。在这里,我只向outer提供了两次相同的向量(行)和函数减法
-
操作符。我在我的解决方案中添加了一点,以生成一个自包含函数,该函数作用于数据帧并排除任何非数字的内容<代码>外部
功能非常强大,我只是希望我能记得更多地使用它。至于drop_string=T?没有这样的运气,但是有一个
is的
sapply
。数值查询很好。非常好。我同意outer功能非常强大,对于更大的矩阵,这将是一种方法,而不是指定每个列或值。注意:由于此答案更具普遍性,因此它可能也更慢,不确定问题速度有多快(即您的数据集有多大).在这种情况下,速度不是问题,但我会记住这一点。谢谢你,泰勒。哪一辆是最快的?还是更有效?
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)
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)
 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)