使用dplyr根据条件分组计算行数
我有一个数据框,如下所示:使用dplyr根据条件分组计算行数,r,dplyr,R,Dplyr,我有一个数据框,如下所示: position_time telematic_trip_no lat_dec lon_dec 1 2016-06-05 00:00:01 526132109 -26.6641 27.8733 2 2016-06-05 00:00:01 526028387 -26.6402 27.8059 3 2016-06-05 00:00:01 526081476 -26.5545 28.3263 4 2016-0
position_time telematic_trip_no lat_dec lon_dec
1 2016-06-05 00:00:01 526132109 -26.6641 27.8733
2 2016-06-05 00:00:01 526028387 -26.6402 27.8059
3 2016-06-05 00:00:01 526081476 -26.5545 28.3263
4 2016-06-05 00:00:04 526140512 -26.5310 27.8704
5 2016-06-05 00:00:05 526140518 -26.5310 27.8704
6 2016-06-05 00:00:19 526006880 -26.5010 27.8490
is_stolen hour_of_day time_of_day day_of_week lat_min
1 0 0 0 Sunday -26.6651
2 0 0 0 Sunday -26.6412
3 0 0 0 Sunday -26.5555
4 0 0 0 Sunday -26.5320
5 0 0 0 Sunday -26.5320
6 0 0 0 Sunday -26.5020
lat_max lon_max lon_min
1 -26.6631 27.8743 27.8723
2 -26.6392 27.8069 27.8049
3 -26.5535 28.3273 28.3253
4 -26.5300 27.8714 27.8694
5 -26.5300 27.8714 27.8694
6 -26.5000 27.8500 27.8480
现在我要做的是计算每一行的行数,其中is_sleet=1,数据帧中满足以下条件的行数:
- lat_dec和lon_dec位于lat_max、lat_min、lon_max和lon_min之间(即,安装在GPS点周围的“框”内)
- 日的时间和周的日期与兴趣行的时间相同
- 行的远程信息处理路径号需要与感兴趣行的不同
- 最后,匹配行的is_被盗标记需要等于0
ps如果你好奇的话,我真的想计算一辆被盗汽车在一次典型的旅行中经过多少辆车:)根据你对问题的描述,下面应该可以
library(dplyr)
library(stats)
# df is the data.frame (see below)
df <- cbind(ID=seq_len(nrow(df)),df)
r.stolen <- which(df$is_stolen == 1)
r.not <- which(df$is_stolen != 1)
print(df[rep(r.not, times=length(r.stolen)),] %>%
setNames(.,paste0(names(.),"_not")) %>%
bind_cols(df[rep(r.stolen, each=length(r.not)),], .) %>%
mutate(in_range = as.numeric(telematic_trip_no != telematic_trip_no_not & time_of_day == time_of_day_not & day_of_week == day_of_week_not & lat_dec >= lat_min_not & lat_dec <= lat_max_not & lon_dec >= lon_min_not & lon_dec <= lon_max_not)) %>%
group_by(ID) %>%
summarise(count = sum(in_range)) %>%
arrange(desc(count)))
而是在管道里
我已经使用以下数据片段对此进行了测试
df <- structure(list(position_time = structure(c(1L, 1L, 1L, 2L, 3L,
4L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), .Label = c("2016-06-05 00:00:01",
"2016-06-05 00:00:04", "2016-06-05 00:00:05", "2016-06-05 00:00:19",
"2016-06-05 00:00:20", "2016-06-05 00:00:22", "2016-06-05 00:00:23",
"2016-06-05 00:00:35", "2016-06-05 00:09:34", "2016-06-06 01:00:06"
), class = "factor"), telematic_trip_no = c(526132109L, 526028387L,
526081476L, 526140512L, 526140518L, 526006880L, 526017880L, 526027880L,
526006880L, 526006890L, 526106880L, 526005880L, 526007880L),
lat_dec = c(-26.6641, -26.6402, -26.5545, -26.531, -26.531,
-26.501, -26.5315, -26.5325, -26.501, -26.5315, -26.5007,
-26.5315, -26.5315), lon_dec = c(27.8733, 27.8059, 28.3263,
27.8704, 27.8704, 27.849, 27.88, 27.87, 27.849, 27.87, 27.8493,
27.87, 27.87), is_stolen = c(0L, 0L, 0L, 0L, 0L, 0L, 1L,
1L, 1L, 1L, 1L, 1L, 1L), hour_of_day = c(0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), time_of_day = c(0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 9L, 0L), day_of_week = structure(c(2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L), .Label = c("Monday",
"Sunday"), class = "factor"), lat_min = c(-26.6651, -26.6412,
-26.5555, -26.532, -26.532, -26.502, -26.532, -26.532, -26.502,
-26.532, -26.502, -26.532, -26.532), lat_max = c(-26.6631,
-26.6392, -26.5535, -26.53, -26.53, -26.5, -26.53, -26.53,
-26.5, -26.53, -26.5, -26.53, -26.53), lon_max = c(27.8743,
27.8069, 28.3273, 27.8714, 27.8714, 27.85, 27.8714, 27.8714,
27.85, 27.8714, 27.85, 27.8714, 27.8714), lon_min = c(27.8723,
27.8049, 28.3253, 27.8694, 27.8694, 27.848, 27.8694, 27.8694,
27.848, 27.8694, 27.848, 27.8694, 27.8694)), .Names = c("position_time",
"telematic_trip_no", "lat_dec", "lon_dec", "is_stolen", "hour_of_day",
"time_of_day", "day_of_week", "lat_min", "lat_max", "lon_max",
"lon_min"), class = "data.frame", row.names = c(NA, -13L))
正如预期的那样,带有的附加行从带有ID=7的7行开始
如果一个人改为按远程信息处理\u trip\u no
分组,我们得到的结果是:
# A tibble: 7 x 2
telematic_trip_no count
<int> <dbl>
1 526006890 2
2 526106880 1
3 526005880 0
4 526006880 0
5 526007880 0
6 526017880 0
7 526027880 0
#一个tible:7 x 2
远程信息处理\u跳闸\u不计算
1 526006890 2
2 526106880 1
3 526005880 0
4 526006880 0
5 526007880 0
6 526017880 0
7 526027880 0
作为警告,上述方法确实会消耗内存。最坏情况下,行数增长到N^2/4
,其中N
是原始数据帧中的行数,用于评估条件的数据帧的列数加倍。与大多数阵列处理技术一样,速度和内存之间存在权衡
希望这能有所帮助。有一个新特性非等联接,它使条件联接非常简单。使用@aichao的数据:
require(data.table) # v1.9.7+
setDT(df)[, ID := .I] # add row numbers
not_stolen = df[is_stolen == 0L]
is_stolen = df[is_stolen == 1L]
not_stolen[is_stolen,
.(ID = i.ID, N = .N - sum(telematic_trip_no == i.telematic_trip_no)),
on = .(time_of_day, day_of_week, lat_min <= lat_dec,
lat_max >= lat_dec, lon_min <= lon_dec, lon_max >= lon_dec),
by=.EACHI][, .(ID, N)]
# ID N
# 1: 7 NA
# 2: 8 NA
# 3: 9 0
# 4: 10 2
# 5: 11 1
# 6: 12 NA
# 7: 13 NA
require(data.table)#v1.9.7+
setDT(df)[,ID:=.I]#添加行号
未被盗=df[被盗==0L]
被偷=df[被偷=1L]
不是被偷的,
(ID=i.ID,N=.N-sum(远程通信跳闸号==i.远程通信跳闸号)),
on=(一天中的时间,一周中的日期,纬度=纬度,纬度=纬度,
by=.EACHI][,(ID,N)]
#身份证号码
#1:7 NA
#2:8 NA
# 3: 9 0
# 4: 10 2
# 5: 11 1
#6:12 NA
#7:13 NA
部分未被窃取[被窃取,
执行类似于联接操作的子集。。即,对于中的每一行,提取匹配的行索引(基于提供给on=
参数的条件)
by=.EACHI
确保,对于i
(第一)参数中的每一行,这里的在相应的匹配行索引上被窃取
,在j
中提供的表达式,第二个参数,(ID=i.ID,N=.N-sum(远程通信\u trip\u no==i.telematic\u trip\u no)),
进行计算。这将返回上面显示的结果
HTH.dput()
足够的数据,包括必要的条件,将有助于其他人帮助您。您是否也可以包括不起作用的“for-loop”代码?“感兴趣的行”指的是什么?您是否选择一行,然后将其与所有其他行进行比较?尝试使用which()
语句来创建满足所有条件的行的子集。这样,它只需在提取相应数据时对数据集进行一次迭代。您可能需要两到四条语句的序列来保持人类可读性和紧凑性,但通常比复杂循环更快、更不容易出错。下面是C运行说明。我正在寻找这样的连接函数。很高兴知道。谢谢。
# A tibble: 7 x 2
telematic_trip_no count
<int> <dbl>
1 526006890 2
2 526106880 1
3 526005880 0
4 526006880 0
5 526007880 0
6 526017880 0
7 526027880 0
require(data.table) # v1.9.7+
setDT(df)[, ID := .I] # add row numbers
not_stolen = df[is_stolen == 0L]
is_stolen = df[is_stolen == 1L]
not_stolen[is_stolen,
.(ID = i.ID, N = .N - sum(telematic_trip_no == i.telematic_trip_no)),
on = .(time_of_day, day_of_week, lat_min <= lat_dec,
lat_max >= lat_dec, lon_min <= lon_dec, lon_max >= lon_dec),
by=.EACHI][, .(ID, N)]
# ID N
# 1: 7 NA
# 2: 8 NA
# 3: 9 0
# 4: 10 2
# 5: 11 1
# 6: 12 NA
# 7: 13 NA