计算多列

时间:2017-05-30 19:00:22

标签: r dplyr

我正在尝试通过计算2列的前n个值来创建几个新列。

使用Auto的示例。我制作了一个列,计算前两个模型年的每千磅平均马力:

library(ISLR)
library(dplyr)    
LaggedAuto <- Auto %>% 
                  arrange(year) %>% 
                  group_by(name) %>% 
                  mutate(L2HPbyWT = 1000*((lag(horsepower)+lag(horsepower,2))/(lag(weight)+lag(weight,2))))

所以80,81,82 Corollas的(重量,HP)是(2265,75),(2350,75),(2245,70)。因此,Corolla '82行上的新列将为1000*(75+75)/(2265+2350) = 32.50。所以它或多或少是HP/Weight的平均值,加权Weight

在我自己的数据集中,大约有12列我想要这样做,滞后为5+。这意味着如果我继续使用当前的技术,我将进行大量的输入(滞后(,1)+滞后(,2)+ ... +滞后(,5))11个更多的变量使得很难更新/好办法。有没有办法以一种简单的方式对多个变量执行这种滞后加权计算以获得不同的滞后?

我有一种感觉,我想根据我之前的一个问题和我发现的另一个问题(Mutate multiple / consecutive columns (with dplyr or base R))使用zoo :: rollaplyr,但我在确定函数是什么时遇到问题。为了保持这个例子,你能否帮我弄清楚如何计算MPGdisplacementacceleration的最后两个实例的平均值1000lbs weight

1 个答案:

答案 0 :(得分:0)

首先,请说明数据来源,以便我们使用。我在library(ISLR)下找到了它。

所以,我讨厌stats :: lag函数。从滞后函数添加滞后值是错误的。我会告诉你我的意思:

lag(Auto$horsepower[1:8], 1)
#[1] 130 165 150 150 140 198 220 215
#attr(,"tsp")
#[1] 0 7 1

lag(Auto$horsepower[1:8], 2)
#[1] 130 165 150 150 140 198 220 215
#attr(,"tsp")
#[1] -1  6  1

lag(Auto$horsepower[1:8], 1) + lag(Auto$horsepower[1:8], 2)
#[1] 260 330 300 300 280 396 440 430
#attr(,"tsp")
#[1] 0 7 1

这不起作用。它为您提供了正确分配数据的方法,但实际上并不可用。你真正想要的是:

shift(Auto$horsepower[1:8], 1:2)
#     [,1] [,2]
#[1,]    0    0
#[2,]  130    0
#[3,]  165  130
#[4,]  150  165
#[5,]  150  150
#[6,]  140  150
#[7,]  198  140

rowSums(shift(Auto$horsepower[1:8], 1:2))
#[1]   0 130 295 315 300 290 338 418

这将是一个完美的矢量化功能,可以让某人的生活更轻松,无论是领先还是滞后。 所以我在下面写了:

  shift <- function(x, i = 1, NA2zero = TRUE, naming = NULL){
  Z <- ifelse(NA2zero, 0, NA)
  L <- sapply(i, function(i){ "if"(i > 0, 
                                     c(rep(Z, max(abs(i))), 
                                       x[-c((length(x)+1-i):length(x))]),
                                     "if"(i < 0, 
                                             c(x[-c(1:abs(i))], 
                                               rep(Z, max(abs(i))) ),
                                             x))
              })
  "if"(is.null(naming), 
       colnames(L) <- paste0(deparse(substitute(x)),".",i),
       colnames(L) <- paste0(naming,".",i))
  return(L)
}

现在,您可以轻松地使用以下方法修复代码:

L2HPbyWT = 1000*((rowSums(shift(Auto$horsepower, i = 1:2)) / rowSums(shift(Auto$weight, i = 1:2))))

我甚至添加了一个有趣的小命名能力:

head(shift(Auto$horsepower, 0:2, naming = "HP"),3)
     HP.0 HP.1 HP.2
[1,]  130    0    0
[2,]  165  130    0
[3,]  150  165  130

编辑:看来你从来不需要延迟功能! 现在我可以深入探讨你的问题。我从来没有进入dplyr所以这将在基地,所以请原谅我。看起来你已经落后于不同年代的汽车了。所以,如果我们看看汽车:     昏暗(自动)     #[1] 392 9#相当大,很多行。

# split them into groups by type of car
eachAuto <- split(Auto, Auto$name)
table(sapply(eachAuto, nrow))
#  0   1   2   3   4   5 # lengths
#  3 245  34  12   7   3 # counts

现在我们看到有3辆车有0行(有一些因素级别没有数据),245辆车只有1排,12辆车有3排,依此类推。

在这里使用名称列似乎是一个错误...除非我们限制我们可以使用的汽车? 怎么样:

MAXLAG <- 2
Autos_subset <- eachAuto[sapply(eachAuto, nrow) > (MAXLAG-1)]
newAuto <- lapply(Autos_subset, function(x) {
  x$L2HPbyWT <- 1000*((rowSums(shift(x$horsepower, i = 1:MAXLAG)) / rowSums(shift(x$weight, i = 1:MAXLAG))))
  x
  })

length(newAuto) # 56 car names in the list 

现在你准确地只使用可用于滞后的汽车了。如果我错过了标记,请告诉我,因为我很可能。