使用dplyr::mutate将函数的参数化应用于单个数据帧列,然后将结果保存到新列?

使用dplyr::mutate将函数的参数化应用于单个数据帧列,然后将结果保存到新列?,r,dataframe,dplyr,R,Dataframe,Dplyr,假设我有一个如下所示的数据帧: user_id date weight 12345 2016-03-07 160 12345 2016-03-06 158 12345 2016-03-05 156 12345 2016-03-04 154 我想通过将多个函数应用于weight列,然后将每个应用程序的结果保存到一个新列,来改变这个数据帧。需要注意的是,这个函数是参数化的,我想将参数值附加到新的列名中。例如,如果我使用lag():

假设我有一个如下所示的数据帧:

user_id  date          weight
12345    2016-03-07    160
12345    2016-03-06    158
12345    2016-03-05    156
12345    2016-03-04    154
我想通过将多个函数应用于
weight
列,然后将每个应用程序的结果保存到一个新列,来改变这个数据帧。需要注意的是,这个函数是参数化的,我想将参数值附加到新的列名中。例如,如果我使用
lag()

其中第一个新列是滞后(重量,1)的结果,第二个是滞后(重量,2)的结果,依此类推

我试着遵循dplyr关于该主题的小插曲中提出的标准评估方法,以及来自的建议,但这两种方法似乎都不能解决参数化函数的问题(否则我只会使用
funs()
!)


我该如何解决这个问题呢?

这里有一个解决方案应该有效(不过可能有更干净的方法)

#假设滞后值设置如下

lag_valsdplyr::标准评估的突变溶液:

tab %>% mutate_(.dots = setNames(lapply(1:4, function(i) lazyeval::interp(~lag(weight, i),
        weight = as.name("weight"))), paste0("weight_", 1:4)))
#   user_id       date weight weight_1 weight_2 weight_3 weight_4
# 1   12345 2016-03-07    160       NA       NA       NA       NA
# 2   12345 2016-03-06    158      160       NA       NA       NA
# 3   12345 2016-03-05    156      158      160       NA       NA
# 4   12345 2016-03-04    154      156      158      160       NA
编辑:这有点整洁

lags = 3
lag_weight <- function(i) lazyeval::interp(~lag(weight, i), weight = as.name("weight"))
tab %>% mutate_(.dots = setNames(lapply(1:lags, lag_weight), paste0('weight_', 1:lags)))
#   user_id       date weight weight_1 weight_2 weight_3 weight_4
# 1   12345 2016-03-07    160       NA       NA       NA       NA
# 2   12345 2016-03-06    158      160       NA       NA       NA
# 3   12345 2016-03-05    156      158      160       NA       NA
# 4   12345 2016-03-04    154      156      158      160       NA
lags=3
滞后权重%变异(dots=setNames(lappy(1:lags,滞后权重),paste0('weight',1:lags)))
#用户id日期重量重量重量重量重量1重量重量2重量3重量4
#12345 2016-03-07 160不适用
#12345 2016-03-06 158 160不适用
#312345 2016-03-05 156 158 160 NA
#4 12345 2016-03-04 154 156 158 160北美

要使用
dplyr
以编程方式添加单个列,可以使用

x <- 2
mutate_(df, .dots = setNames(list(~lag(weight, x)), paste0('dweight_', x)))

您可以随心所欲地编辑该函数:添加一个数据帧参数以便链接它,使用
*apply
而不是
for
,添加一个参数以传递函数,等等。您可以使用
tidyquant::tq\u mutate
来解决此问题。 这里是一个玩具的例子

# Get Stock Prices from Yahoo! Finance

# Create a vector of stock symbols
FANG_symbols <- c("FB", "AMZN", "NFLX", "GOOG")

# Pass symbols to tq_get to get daily prices
FANG_data_d <- FANG_symbols %>%
    tq_get(get = "stock.prices", from = "2014-01-01", to = "2016-12-31")

# Show the result
FANG_data_d

FANG_data_d %>%
    select(symbol, date, adjusted) %>%
    group_by(symbol) %>%
    tq_mutate(
        select     = adjusted,
        mutate_fun = lag.xts,
        k          = 1:5,
        col_rename = column_names
    )
#从雅虎获取股票价格!财务
#创建股票符号向量
方欧符号%
选择(符号、日期、调整)%>%
分组依据(符号)%>%
tq_突变(
选择=调整,
mutate_fun=lag.xts,
k=1:5,
col\u rename=列名称
)
参考


丹乔,马特。2017“演示周:课程(星期一)使用
library(data.table);setDT(DT)[,paste0(“weight”,1L:nrow(DT)):=shift(weight,1L:.N)可以非常轻松地完成此任务。”
例如。@lukeA您的代码对我不起作用。@DavidArenburg这是一个很有帮助的解决方案,它提醒我们
数据表
解决方案是多么简洁。这太好了,谢谢!我希望避免循环,但这很容易阅读,同时提供了您建议的灵活性。随着循环的进行,这是一个非常好的解决方案,因为它是vectorized(不是逐个元素构建列元素);在示例中它只运行四次。如果您愿意,可以重写它以使用
*apply
函数、preallocate等。但是,除非您添加大量列,否则时间差可能不会太大。
x <- 2
mutate_(df, .dots = setNames(list(~lag(weight, x)), paste0('dweight_', x)))
dweight <- function(l = 1){
  for (i in l){
    df <- mutate_(df, .dots = setNames(list(~lag(weight, i)), paste0('dweight_', i)))
  }
  df
}
> dweight(1:4)
  user_id       date weight dweight_1 dweight_2 dweight_3 dweight_4
1   12345 2016-03-07    160        NA        NA        NA        NA
2   12345 2016-03-06    158       160        NA        NA        NA
3   12345 2016-03-05    156       158       160        NA        NA
4   12345 2016-03-04    154       156       158       160        NA
# Get Stock Prices from Yahoo! Finance

# Create a vector of stock symbols
FANG_symbols <- c("FB", "AMZN", "NFLX", "GOOG")

# Pass symbols to tq_get to get daily prices
FANG_data_d <- FANG_symbols %>%
    tq_get(get = "stock.prices", from = "2014-01-01", to = "2016-12-31")

# Show the result
FANG_data_d

FANG_data_d %>%
    select(symbol, date, adjusted) %>%
    group_by(symbol) %>%
    tq_mutate(
        select     = adjusted,
        mutate_fun = lag.xts,
        k          = 1:5,
        col_rename = column_names
    )