x的法术差异,加上x

时间:2016-07-11 14:36:30

标签: r dataframe dplyr plyr

我有一个这样的数据框:

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         

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

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

在Express 0下获取ID为“S36”的sum.dist为:

18-15 = 3

这同样适用于其他人。

发生了什么(弗兰克的猜测):我们测量了行程中不同点的油耗和距离,并想知道在“快速”和“本地”阶段我们使用了多少油耗

完全正确的Frank Guess ,我希望获得每种类型的效率(Express和Local)。这是我的项目,我不知道如何处理。谢谢弗兰克!

3 个答案:

答案 0 :(得分:4)

好的,我想我现在明白了,感谢@ 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

注意

  

您不需要第二个group_by语句,因为最后一个分组级别(r)是"剥离"由第一个summarise_each。 - docendo discimus

工作原理:来自data.table包的rleid标识"运行"值是不变的。如果您安装了data.table,则可以data.table::rleid代替rleid,并跳过使用library加载包。

答案 1 :(得分:4)

使用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

在丑陋的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),它会表现得很奇怪。
  • 如果'旅行'被破坏(即在快递结束之前同一个id的本地旅行开始),将不会很好地工作,我不知道它是否会发生在你的数据集中

答案 2 :(得分:3)

使用与{Frank's帖子中的data.table方法类似的dplyr

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