Объединение таблиц, смещение или переименование существующих столбцов на основе значения в другом столбце - PullRequest
0 голосов
/ 24 сентября 2019

Я импортировал таблицу (Table1) в следующем формате:

ID    Name    Age   Start    Status1    Status2    Status3    Status4    Status5   Status6
01    John     45    2011         25         13         13         12         34        35
02    Mike     23    2017         12         15         18         45         32        25
03   Peter     34    2019         34         12         15         19         24        27
04   Sarah     21    2020         45         46         47         48         49        50

И я создал другую таблицу (Table2), которая выглядит следующим образом:

ID    Name    Age   Start    Year    Value
02    Mike     23    2017       3       24
03   Peter     34    2019       1       11
03   Peter     34    2019       2       13
03   Peter     34    2019       3       13
04   Sarah     21    2020       1       42
04   Sarah     21    2020       2       43
04   Sarah     21    2020       3       44

Table2 содержитпрогнозируемые значения на первые 3 года после и включая начало, НО только в том случае, если три года еще не прошли (по состоянию на текущий год, 2019).Таким образом, в приведенном выше примере, ID 01 уже более 3 лет прошло их начальное значение, поэтому не имеют никаких прогнозов;Идентификатор 02 через два года прошел их начальное значение, поэтому имеет один прогноз;Идентификаторы 03 и 04 - нулевые годы, прошедшие начальное значение, поэтому у нас есть три прогноза.

Мне нужно переместить значения из таблицы 2 в таблицу 1, заменив значения состояния и сдвинув их вправо.Финальная таблица должна выглядеть следующим образом:

ID    Name    Age   Start    Status1    Status2    Status3    Status4    Status5   Status6
01    John     45    2011         25         13         13         12         34        35
02    Mike     23    2017         24         12         15         18         45        32
03   Peter     34    2019         11         13         13         34         12        15
04   Sarah     21    2020         42         43         44         45         46        47

Как можно надеяться, строка для идентификатора 01 остается неизменной.Для идентификатора 02 старые значения статуса сместились на один вправо, а статус1 был заменен.Для идентификаторов 03 и 04 старые значения Status сместились на три позиции вправо, а Status1 на Status3 были заменены.Как видите, старые значения, которые были от Status4 до Status6, были удалены.

Я застрял в этом.До сих пор я пытался сформулировать некоторые правила для замен следующим образом:

1) Если Год больше 3 лет от текущего года (2019), оставьте названия столбцов Статус такими, как они есть.например, строка 1 таблицы 1.

2) Если значение «Пуск» равно 2019 или выше, переименуйте столбцы «Состояние», добавив 3. Например, в строках 3 и 4 таблицы 1 «Состояние1» следует переименовать в «Status4» и т. д.Последние 3 столбца состояния (от Status4 до Status6) будут удалены.

3) Если Start находится в пределах 3 лет с 2019 года (т. Е. С 2017 по 2019), переименуйте столбцы Status, добавив разницу между 2016 и Start.,например, в строке 2 таблицы 1 Status1 будет переименован в Status2 и так далее.Последний столбец (Status6) будет удален.

Я мог бы закодировать их, используя if / else, но я не уверен, как разместить их в конвейере обработки данных с помощью select () и left_join () для переносаэти изменения успешно.Я использую R, но мог бы также использовать SQL, если бы это было проще.Любая помощь будет высоко ценится.

ps Я ценю, что результирующая таблица находится в странном формате, но, к сожалению, это то, что мне нужно произвести.

Ответы [ 2 ]

2 голосов
/ 24 сентября 2019

Вот решение data.table.Большая часть ответа сводится к функции merge_row, которая принимает объединенный вектор предсказанных значений и значений состояния, удаляет NA s, а затем усекает вектор до 6 элементов.Он возвращает список, потому что это то, что data.table ожидает от RHS при использовании :=.


library(data.table)
set.seed(1234)

## Building data

table1 <- data.table(ID = 1:10,
                     Name = LETTERS[1:10],
                     Age = rpois(10, 40),
                     Start = sample(2015:2020, 10, rep = T),
                     Status1 = rpois(10, 10),
                     Status2 = rpois(10, 10),
                     Status3 = rpois(10, 10),
                     Status4 = rpois(10, 10),
                     Status5 = rpois(10, 10),
                     Status6 = rpois(10, 10))
res = list()
for(i in 1:nrow(table1)) {
  if(table1[i,Start] <= 2016) {
    res[[i]] <- NULL
  } else {
    y <- table1[i, Start]
    n_y <- min(3, 3 - (2019-y))
    res[[i]] <- table1[i,
           cbind(.SD[,.(ID, Name, Age, Start)], 
                 Year = seq_len(n_y),
                 Value = rpois(n_y, 20))]
  } 
}
table2 <- do.call(rbind, res)
merge_row <- function(x) {
  x = x[!is.na(x)][1:6]
  return(lapply(1:6, FUN = function(i) x[i]))
}

## Doing the merge

merged_table <- merge(dcast(table2, ID + Name + Age + Start ~ Year, value.var = 'Value'), 
                      table1, 
                      all = TRUE)[, 
                                  paste0('Status', 1:6) := 
                                    merge_row(c(`1`, `2`, `3`, Status1, 
                                                 Status2, Status3, Status4, 
                                                 Status5, Status6)),
                                  ID][,c('1', '2', '3') := NULL][]
merged_table
#>     ID Name Age Start Status1 Status2 Status3 Status4 Status5 Status6
#>  1:  1    A  32  2019      23      22      18       8      15       8
#>  2:  2    B  41  2018      29      17       8       5      11      10
#>  3:  3    C  42  2017      20      11      14      15      13      10
#>  4:  4    D  35  2018      21      19       7       6      12      16
#>  5:  5    E  43  2019      19      17      19       8      14      18
#>  6:  6    F  36  2016      10       8       9      11      12       6
#>  7:  7    G  46  2019      18      19      20      10      13       7
#>  8:  8    H  36  2016      12      14       8      10      11      11
#>  9:  9    I  36  2020      23      16      19      13       6      11
#> 10: 10    J  28  2017      19      20       8       9       7       9

Создано в 2019-09-24 пакетом Представить (v0.3.0)

1 голос
/ 25 сентября 2019

Другой вариант - привязать таблицу 2 к длинному формату таблицы 1, взять 6 верхних значений и снова развернуть в широкоформатный формат:

idcols <- c("ID","Name","Age","Start")
dcast(
    rbindlist(list(Table2,
        melt(Table1, id.vars=idcols, variable.name="Year", value.name="Value")))[,
            .(Status=paste0("Status", 1:6), Value=head(Value, 6)), idcols],
    as.formula(paste(paste(idcols, collapse=" + "), "~ Status")), value.var="Value")

вывод:

   ID  Name Age Start Status1 Status2 Status3 Status4 Status5 Status6
1:  1  John  45  2011      25      13      13      12      34      35
2:  2  Mike  23  2017      24      12      15      18      45      32
3:  3 Peter  34  2019      11      13      13      34      12      15
4:  4 Sarah  21  2020      42      43      44      45      46      47

данные:

library(data.table)
Table1 <- fread("ID    Name    Age   Start    Status1    Status2    Status3    Status4    Status5   Status6
01    John     45    2011         25         13         13         12         34        35
02    Mike     23    2017         12         15         18         45         32        25
03   Peter     34    2019         34         12         15         19         24        27
04   Sarah     21    2020         45         46         47         48         49        50")
Table2 <- fread("ID    Name    Age   Start    Year    Value
02    Mike     23    2017       3       24
03   Peter     34    2019       1       11
03   Peter     34    2019       2       13
03   Peter     34    2019       3       13
04   Sarah     21    2020       1       42
04   Sarah     21    2020       2       43
04   Sarah     21    2020       3       44")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...