我有一个这样的数据框:
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)。这是我的项目,我不知道如何处理。谢谢弗兰克!
答案 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
缺点我能想到:
答案 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