Учитывая ваше описание проблемы, должен работать
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)))
В первой строке просто добавляется столбец с именем ID
- df
, который идентифицирует строку по ее номеру строки, которую мы можем позже dplyr::group_by
, чтобы сделать счет.
Следующие две строки делят ряды на украденные и не украденные автомобили. Ключ к:
- повторности каждый ряд угнанных автомобилей
N
раз, когда N
является количество не-украденных строк автомобиля,
- копируют ряды не-угнанных автомобилей (в виде блока)
M
раз, где M
это число украденных строк автомобилей, а также
- добавить результат (2) в (1) в качестве новых столбцов и изменить имена этих новых столбцов, так что мы можем ссылаться на них в состоянии
Результат (3) га ve строк, которые перечисляют все пары украденных и не украденных строк из исходного фрейма данных, так что ваше условие может применяться в массиве.dplyr
конвейерный R рабочего процесса, четвертая строка кода (завернутый в print()
) делает это:
- первая команда копирует не-украденных строк автомобиля с помощью
times
- вторая команда добавляет
_not
к имена столбцов, чтобы отличить их от украденных столбцов автомобилей, когда мы привязываем столбцы. Благодаря this SO answer для этого драгоценного камня.
- третья команда копирует украденные строки автомобиля, используя
each
и присоединяет предыдущий результат как новые столбцы, используя dplyr::bind_cols
- четвертой команды использует
dplyr::mutate
, чтобы создать новый столбец с именем in_range
, который является результатом применения условия. Логический результат преобразуется в {0,1}
, чтобы обеспечить легкое накопление
- Остальная часть команд в трубе составляет
in_range
, сгруппированных по ID
и размещая результаты в порядке убывания количества. Обратите внимание, что теперь ID
это столбец, который идентифицирует строки исходного кадра данных, для которых is_stolen = 1
тогда ID_not
это столбец для строк, которые is_stolen = 0
Это предполагает, что вы хотите счетчик для каждой строки, is_stolen = 1
в исходных данных кадр, что вы сказали в своем вопросе. Если вместо этого вы действительно хотите, чтобы счетчик для каждого telematic_trip_no
, который украден, то вы можете использовать
group_by(telematic_trip_no) %>%
в трубе вместо.
Я проверил это, используя следующие данные фрагмент
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(9L, 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))
Здесь я приложил 7
новые строки с is_stolen = 1
к исходным 6
строк, все is_stolen = 0
:
- первый добавлен ряд с
telematic_trip_no = 526005880
нарушает условие долготы для всех не украденных рядов, поэтому его счет должен быть 0
- на второй добавленной строке с
telematic_trip_no = 526006880
нарушает условие широты для всех не-украденных строк, поскольку его счет должен быть 0
- третий добавлен ряд с
telematic_trip_no = 526007880
нарушает условие telematic_trip_no
для всех не-украденных строк, поскольку его счет должен быть 0
- четвертая добавлена строка с
telematic_trip_no = 526006890
удовлетворяет условие для строк 4
и 5
, которые не-украдены, поскольку его счет должна быть 2
- пятой добавлена строка с
telematic_trip_no = 526106880
удовлетворяет условие для строки 6
, что не-украден, поэтому его счет должен быть 1
- шестой добавлен ряд с
telematic_trip_no = 526017880
нарушает условие time_of_day
для всех не-украденных строк, поскольку его счет должен быть 0
- седьмой добавляются строка с
telematic_trip_no = 526027880
нарушает условие day_of_week
для всех не-украденных строк, поэтому его кол должны быть 0
Выполнение кода на этих данных дает:
# A tibble: 7 x 2
ID count
<int> <dbl>
1 10 2
2 11 1
3 7 0
4 8 0
5 9 0
6 12 0
7 13 0
, который, как ожидается, напомнив, что приложенные строки с is_stolen = 1
начинаются в строке 7
с ID = 7
.
Если один сгруппировали по telematic_trip_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
Как предостережение, вышеописанный подход делает стоимость памяти. В худшем случае количество строк растет до N^2/4
, где N
- это количество строк в исходном фрейме данных, а количество столбцов удваивается для фрейма данных, который используется для оценки условия. Как и в большинстве методов обработки массивов, между скоростью и памятью существует торговля.
Надеюсь, что это поможет.
'dput()' из достаточного количества данных, которое включает в себя необходимые условия, помогая другим помочь вам. – hrbrmstr
Можете ли вы также включить код «для цикла», который не работает? – Sotos
Что означает «ряд интересов»? Вы выбираете одну строку, а затем сравниваете ее со всеми остальными строками? – Tav