как объединить указанные c значения фрейма данных R - PullRequest
0 голосов
/ 14 января 2020

У меня есть фрейм данных, который отображает использование некоторых устройств, как показано в примере ниже df. Одна строка представляет одно оборудование, а каждый столбец представляет определенный c час дня. Значения выше нуля - это часы, в которые оборудование включено, а значения ноль - когда оно выключено. Мне нужно извлечь для каждого оборудования все периоды времени, когда они были включены. Проблема в том, что оборудование использует разное количество использования в один и тот же день, и мне нужно извлечь эти периоды для всех из них. Кто-нибудь знает, как решить эту проблему?

df = data.frame(hour_1 = c(1, 1, 1, 0, 0, 1), hour_2 = c(2, 2, 2, 0, 2, 2), hour_3 = c(3, 3, 3, 0, 3, 3),
            hour_5 = c(5, 5, 0, 0, 0, 0), hour_6 = c(0, 0, 0, 0, 0, 0), hour_7 = c(0, 0, 0, 7, 7, 0),
            hour_8 = c(0, 0, 0, 0, 0, 0), hour_9 = c(9, 9, 0, 0, 9, 9), hour_10 = c(10, 10, 10, 10, 10, 10))

Ответы [ 2 ]

0 голосов
/ 15 января 2020

Я не уверен, правильно ли я вас понимаю. Согласно комментарию под вашим вопросом, вы хотите группу векторов для каждой машины; один вектор для каждого периода, в течение которого машина работала, с указанием количества часов работы машины. Поскольку число векторов может быть разным для каждой машины, оно не помещается в фрейм данных.

Тем не менее, вот одна строка, которая даст вам список с этой информацией.

lapply(split.data.frame((as.matrix(df)>0), 1:6), function(x) 
       split(which(x), cumsum(c(0, diff(which(x))-1)))) -> machines

Это приводит к следующему списку:

machines
#> $`1`
#> $`1`$`0`
#> [1] 1 2 3 4
#> 
#> $`1`$`3`
#> [1] 8 9
#> 
#> 
#> $`2`
#> $`2`$`0`
#> [1] 1 2 3 4
#> 
#> $`2`$`3`
#> [1] 8 9
#> 
#> 
#> $`3`
#> $`3`$`0`
#> [1] 1 2 3
#> 
#> $`3`$`5`
#> [1] 9
#> 
#> 
#> $`4`
#> $`4`$`0`
#> [1] 6
#> 
#> $`4`$`2`
#> [1] 9
#> 
#> 
#> $`5`
#> $`5`$`0`
#> [1] 2 3
#> 
#> $`5`$`2`
#> [1] 6
#> 
#> $`5`$`3`
#> [1] 8 9
#> 
#> 
#> $`6`
#> $`6`$`0`
#> [1] 1 2 3
#> 
#> $`6`$`4`
#> [1] 8 9

Поэтому, если вы хотите узнать, когда машина 1 была активна, вы можете сделать:

machines[[1]]
#> $`0`
#> [1] 1 2 3 4
#>
#> $`3`
#> [1] 8 9

Этот вкладыш показывает, как данные могут быть извлечены для получения желаемого результата:

sapply(machines, function(x) 
  paste0("(", paste(sapply(x, 
  function(y){if(length(y)>1) paste(min(y), max(y), sep="-") else y}), collapse = ", "), ')'))
               1                2                3                4 
   "(1-5, 9-10)"    "(1-5, 9-10)"      "(1-3, 10)"        "(7, 10)" 
               5                6 
"(2-3, 7, 9-10)"    "(1-3, 9-10)" 

0 голосов
/ 14 января 2020

Можно было бы преобразовать в «длинный» формат и затем сделать filter

library(dplyr)
library(tidyr)
df %>%
    pivot_longer(everything()) %>%
    filter(value != 0)

Если нам нужен индекс

m1 <- which(df > 0, arr.ind = TRUE)
split(colnames(df)[m1[,2]], m1[,1])

На основании обновления ОП показал

library(data.table)
library(stringr)
df %>%
   mutate(rn = row_number()) %>% 
   pivot_longer(cols = -rn) %>% 
   group_by(grp = rleid(value != 0), rn)  %>%
   filter(any(value != 0)) %>%
   summarise(value = list(range(value))) %>% 
   unnest(c(value)) %>%
   ungroup %>%
    mutate(grp = str_c('period_', match(grp, unique(grp)), letters[rowid(grp)]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...