Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 将函数应用于每行数据帧和返回数据帧列表的有效方法_R - Fatal编程技术网

R 将函数应用于每行数据帧和返回数据帧列表的有效方法

R 将函数应用于每行数据帧和返回数据帧列表的有效方法,r,R,我有一个函数,它接受许多参数并返回一个数据帧。我还有一个数据框,其中每一行都包含我希望传递给函数的参数,并且我希望将生成的数据框集存储在一个列表中。做这件事的有效方法是什么?(我假设这是一种类似于apply的方法。) 例如,假设您有(无意义的)函数 但是如何为数据帧的每一行运行myfunc并将结果存储在列表中呢?我知道如何对此进行基本的for循环,但我正在寻找运行得更快的东西—矢量化的东西。如果您想要一个答案列表,为什么不传递一个参数列表?首先将数据帧拆分为一个列表,然后lappy您的函数: l

我有一个函数,它接受许多参数并返回一个数据帧。我还有一个数据框,其中每一行都包含我希望传递给函数的参数,并且我希望将生成的数据框集存储在一个列表中。做这件事的有效方法是什么?(我假设这是一种类似于apply的方法。)

例如,假设您有(无意义的)函数


但是如何为数据帧的每一行运行myfunc并将结果存储在列表中呢?我知道如何对此进行基本的for循环,但我正在寻找运行得更快的东西—矢量化的东西。

如果您想要一个答案列表,为什么不传递一个参数列表?首先将数据帧拆分为一个列表,然后
lappy
您的函数:

listargs <- split(df,1:nrow(df))

lapply(listargs,myfunc)

$`1`
  x y
1 1 1
2 2 1
3 3 1
4 4 1

$`2`
  x y
1 2 2
2 3 2
3 4 2
4 5 2

$`3`
  x y
1 3 3
2 4 3
3 5 3
4 6 3
require(data.table) ## 1.9.2+
fA <- function(x, y) {
  data.frame(x = x:y, y = y:x)
}
dt = as.data.table(df)
result1 = dt[, list(ans = list(fA(x, y))), by=seq_len(nrow(dt))]
#    seq_len          ans
# 1:       1 <data.frame>
# 2:       2 <data.frame>
# 3:       3 <data.frame>
listargs您的“无意义”函数需要对
apply
有一些意义才能工作。对于初学者,您将无法使用
$
,因为
apply
会将每一行视为基本命名向量

记住这一点,这里有一个重写(还有一个更“卑鄙”的意思):


同样,不要总是太快地注销
循环的
<代码>应用
是优化的,但基本上隐藏了一个for循环

以下是一些速度比较:

## Function to use with `apply`
myfunc <- function(dfRow) {
  data.frame(x = dfRow["y"]:dfRow["x"], y = mean(c(dfRow["x"], dfRow["y"])))
}

## Function to use with `lapply`
myfunc1<-function(dfRow){
  return(data.frame(x=dfRow$x:dfRow$y,y=mean(dfRow$x,dfRow$y)))
}

## Sample data
set.seed(1)
df <- data.frame(x = sample(100, 100, TRUE),
                 y = sample(100, 100, TRUE))

如果您愿意使用外部软件包,那么下面是一个使用
数据的软件包

以下是一个简化功能的版本:

listargs <- split(df,1:nrow(df))

lapply(listargs,myfunc)

$`1`
  x y
1 1 1
2 2 1
3 3 1
4 4 1

$`2`
  x y
1 2 2
2 3 2
3 4 2
4 5 2

$`3`
  x y
1 3 3
2 4 3
3 5 3
4 6 3
require(data.table) ## 1.9.2+
fA <- function(x, y) {
  data.frame(x = x:y, y = y:x)
}
dt = as.data.table(df)
result1 = dt[, list(ans = list(fA(x, y))), by=seq_len(nrow(dt))]
#    seq_len          ans
# 1:       1 <data.frame>
# 2:       2 <data.frame>
# 3:       3 <data.frame>
在这里,我们将数据的子集,
.SD
——一个特殊的变量,它携带属于每个组的数据,传递给函数
fB
。再次执行
result2$ans
应该会得到您的答案

哦,顺便说一句,在代码中使用空格是可以的;成本不高:)

myfunc <- function(dfRow) {
  data.frame(x = dfRow["x"]:dfRow["y"], y = mean(c(dfRow["x"], dfRow["y"])))
}
apply(df, 1, myfunc)
# [[1]]
#   x   y
# 1 1 2.5
# 2 2 2.5
# 3 3 2.5
# 4 4 2.5
# 
# [[2]]
#   x   y
# 1 2 3.5
# 2 3 3.5
# 3 4 3.5
# 4 5 3.5
# 
# [[3]]
#   x   y
# 1 3 4.5
# 2 4 4.5
# 3 5 4.5
# 4 6 4.5
## Function to use with `apply`
myfunc <- function(dfRow) {
  data.frame(x = dfRow["y"]:dfRow["x"], y = mean(c(dfRow["x"], dfRow["y"])))
}

## Function to use with `lapply`
myfunc1<-function(dfRow){
  return(data.frame(x=dfRow$x:dfRow$y,y=mean(dfRow$x,dfRow$y)))
}

## Sample data
set.seed(1)
df <- data.frame(x = sample(100, 100, TRUE),
                 y = sample(100, 100, TRUE))
fun1 <- function() apply(df, 1, myfunc)

fun2a <- function() {
  listargs <- split(df,1:nrow(df))
}

fun3 <- function() {
  out <- vector("list", nrow(df))
  for (i in 1:nrow(df)) {
    out[[i]] <- data.frame(x = df$x[i]:df$y[i], y = mean(c(df$x[i], df$y[i])))
  }
  out
}
microbenchmark(fun2(), fun2(), fun3(), times = 20)
# Unit: milliseconds
#    expr      min       lq   median       uq       max neval
#  fun1() 39.72704 39.99255 40.84243 43.77641  48.16284    20
#  fun2() 74.92324 79.20913 82.15130 83.12488 100.51695    20
#  fun3() 48.61772 49.59304 50.16654 56.17891  88.65290    20
require(data.table) ## 1.9.2+
fA <- function(x, y) {
  data.frame(x = x:y, y = y:x)
}
dt = as.data.table(df)
result1 = dt[, list(ans = list(fA(x, y))), by=seq_len(nrow(dt))]
#    seq_len          ans
# 1:       1 <data.frame>
# 2:       2 <data.frame>
# 3:       3 <data.frame>
require(data.table) ## 1.9.2+
fB <- function(dat) {
  data.frame(x = dat$x:dat$y, y = dat$y:dat$x)
}
dt = as.data.table(df)
result2 = dt[, list(ans = list(fB(.SD))), by=seq_len(nrow(dt))]
#    seq_len          ans
# 1:       1 <data.frame>
# 2:       2 <data.frame>
# 3:       3 <data.frame>