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

时间:2016-03-07 23:05:53

标签: 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    dweight_1    dweight_2    ...
12345    2016-03-07    160       NA           NA   
12345    2016-03-06    158       160          NA
12345    2016-03-05    156       158          160
12345    2016-03-04    154       156          158

第一个新列是lag(weight, 1)的结果,第二个来自lag(weight, 2),依此类推。

我尝试遵循dplyr关于这个主题的小插图中提出的标准评估方法,以及来自this SO question的建议,但似乎都没有解决参数化函数的皱纹(否则我只会使用{{1 }}!)。

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:3)

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

的内容
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

您可以根据需要编辑该功能:添加数据框参数以便链接,使用*apply代替for,添加参数以传递函数等。疯狂。< / p>

答案 1 :(得分:1)

这是一个应该有效的解决方案(虽然可能有更简洁的方法)

# Assuming lag_vals is set as follows
lag_vals <- 1:3
names(lag_vals) <- paste0('dweight_', 1:3)

df_new <- cbind(df, sapply(lag_vals, function(x) { x=lag(df$weight, x) }))
df_new
##   user_id       date weight dweight_1 dweight_2 dweight_3
## 1   12345 2016-03-07    160        NA        NA        NA
## 2   12345 2016-03-06    158       160        NA        NA
## 3   12345 2016-03-05    156       158       160        NA
## 4   12345 2016-03-04    154       156       158       160

答案 2 :(得分:1)

dplyr :: mutate解决方案,标准评估:

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

答案 3 :(得分:0)

您可以使用tidyquant::tq_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
    )

<强>参考

Dancho,马特。 2017年。“演示周:班级(星期一)&lt; - Tidyquant。”http://www.business-science.io/code-tools/2017/10/23/demo_week_tidyquant.html