x 的法术内的差值和 x 相加

Difference within spells of x and add up by x

我有一个这样的数据框:

wpt    ID   Fuel  Dist  Express  
 1     S36   12    1     1         
 2     S36   14    4     1         
 inter S36   15    7     0         
 3     S36   18    10    0         
 inter S36   20    12    1         
 4     S36   23    17    1         
 5     S36   30    20    1         
 6     W09   45    9     0         
 7     W09   48    14    0         
 8     W09   50    15    0         

理想的输出是:

ID    sum.fuel    sum.dist   Express   
S36     12          11          1         
S36     3           3           0         
W09     5           6           0         

注意: 在 ID "S36" 的 Express 1 下获取 sum.dist 的步骤是:

(14-12)+(30-20)=12

要在 ID "S36" 的 Express 0 下获取 sum.dist 是:

18-15=3

其他人也是如此。

发生了什么事(Frank 的猜测):我们测量了旅途中各个点的油耗和距离,并想知道我们在 "express" 和 "local" 阶段。

Frank 猜对了,我想获得每种类型(Express 和Local)的效率。这是我的项目,我不知道如何处理。谢谢弗兰克!

好的,我想我现在明白了,感谢@Tensibai 的解释:

library(data.table)
DF %>% 
  group_by(ID, Express, r = rleid(ID, Express)) %>% 
  summarise_each(funs(last(.) - first(.)), Fuel, Dist) %>%
  group_by(ID, Express) %>%
  summarise_each(funs(sum), Fuel, Dist)


     ID Express  Fuel  Dist
  (chr)   (int) (int) (int)
1   S36       1    12    11
2   S36       0     3     3
3   W09       0     5     6

:

You don't need the second group_by statement since the last grouping level (r) is "peeled off" by the first summarise_each. – docendo discimus

工作原理:data.table 包中的 rleid 标识 "runs" 其中值是常量。如果你安装了 data.table,你可以用 data.table::rleid 代替 rleid 并跳过用 library.

加载包

使用类似于@Frank 的 post.

中的 dplyr 方法的 data.table
library(data.table)
setDT(df1)[, lapply(.SD, function(x) x[.N] - x[1]) , 
     by =  .(ID, Express, Local, r= rleid(ID, Express, Local)), .SDcols = Fuel:Dist
       ][, lapply(.SD, sum) , by = .(ID, Express, Local), .SDcols = Fuel:Dist]
#    ID Express Local Fuel Dist
#1: S36       1     0   12   11
#2: S36       0     1    3    3
#3: W09       0     1    5    6

另一种选择 data.table 而不使用 lapply 来避免循环:

数据集:

data <- read.table(text='wpt    ID   Fuel  Dist  Express   Local
 1     S36   12    1     1         0
                   2     S36   14    4     1         0
                   inter S36   15    7     0         1
                   3     S36   18    10    0         1
                   inter S36   20    12    1         0
                   4     S36   23    17    1         0
                   5     S36   30    20    1         0
                   6     W09   45    9     0         1
                   7     W09   48    14    0         1
                   8     W09   50    15    0         1',header=TRUE,stringsAsFactors=FALSE)

代码:

setDT(data) 
# Make a data.table from the dataframe 
# (could be avoided by reading into a datatable directly)

data[,travel:=rleid(ID,Express)] 
# Generate a unique ID per travel
# (same ID, same Express type contiguous)

result <- data[, list(
  V1=max(Fuel)-min(Fuel),
  V2=max(Dist)-min(Dist)
), by=c('ID','Express','travel')][, list(
  sum.fuel = sum(V1),
  sum.dist = sum(V2)
),by = c('ID','Express')]

给出:

    ID Express sum.fuel sum.dist
1: S36       1       12       11
2: S36       0        3        3
3: W09       0        5        6

在 Ugly oneliner 上,这是一步一步的步骤(由于复制以显示其工作原理,速度较慢):

tmp <- data[, list(
    V1= max(Fuel) - min(Fuel),
    V2= max(Dist) - min(Dist)
), by=c('ID','Express','travel')]

这里我们获取每次行程的 Fuel 和 Dist 值(我在分组子句中保留了 Id 和 Express 以便在第二个回合使用它们)。

    ID Express travel V1 V2
1: S36       1      1  2  3
2: S36       0      2  3  3
3: S36       1      3 10  8
4: W09       0      4  5  6

然后我们将每个旅行类别(Express 0 或 1)与 ID 相加:

result <- tmp[, list(sum.fuel = sum(V1), sum.dist = sum(V2)), by=c('ID','Express')]

输出:

    ID Express sum.fuel sum.dist
1: S36       1       12       11
2: S36       0        3        3
3: W09       0        5        6

缺点我能想到的:

  • 如果计数器循环(例如,99999km 在旧卡车上循环到 0),它会表现得很奇怪
  • 如果 'travels' 被破坏(即同一 id 的本地旅行在快递结束之前开始),将无法很好地工作,我不知道它是否会发生在你的数据集中