По сути, вы назначаете нефильтрованный столбец фрейма данных по отфильтрованным данным, в результате вызывается cbind
, где обе стороны имеют разные строки:
df$stay <- cbind(df[df$mac_address == mac[i,] & df$sensor == sens[j,], ],
stay = cluster$cluster)
Кроме того, предполагая, что dbScan
из того же имени пакет, Документы CRAN указывают, что возвращаемое значение:
Объект класса dbscan_fast со следующими компонентами:
eps значение параметра eps. minPts значение параметра minPts. кластер Целочисленный вектор с назначениями кластера. Ноль указывает на точки шума.
Что может расширять объект R list
этими именованными компонентами вектора, а не одним значением. Кроме того, ваш фильтр фрейма данных может не возвращать строк, поскольку может не быть экземпляров указанного c уникального значения mac_address И sensor . В целом, у вас есть проблемы с длиной с обеих сторон присваивания.
Чтобы исправить это, рассмотрите возможность обертывания вычисления в tryCatch
и, в частности, выбора значения eps
. Также рассмотрите expand.grid
и Map
для поэлементного цикла вместо вложенных for
циклов, в которых вы создаете промежуточный фрейм данных, который объединяется обратно в более крупный:
# DATA FRAME OF ALL POSSIBLE COMBINATIONS
params_df <- expand.grid(mac_address = unique(df$mac_address),
sensor = unique(df$sensor))
# USER-DEFINED METHOD WITH tryCatch FOR FAILED CALCULATIONS
calc_cluster <- function(mac, sens) {
tryCatch({
sub <- df[df$mac_address == mac & df$sensor == sens,]
dbscan(sub$uTime, eps = 300, MinPts = 2)$eps
}, error = function(e) return(NA)
)
}
# COLUMN ASSIGNMENT
params_df$cluster <- Map(calc_cluster, params_df$mac_address, params_df$sensor)
# MERGE TO ORIGINAL DATA FRAME
df <- merge(df, params_df, by=c("mac_address", "sensor"))