Измените столбцы «фактического года» на столбцы, относящиеся к значению в другом столбце. - PullRequest
0 голосов
/ 28 августа 2018

У меня есть таблица данных, которая выглядит следующим образом:

ID    Start_Year    Payment_2010    Payment_2011    Payment_2012    Payment_2013
 1          2010              19              15              NA              11
 2          2012              22              24              26              23
 3          2012              NA              NA              NA              05   
 4          2011              17              NA              14              NA       

Так продолжается для многих строк, в общей сложности около 20 лет столбцов Оплаты.

Мне нужно изменить его, используя R или SQL, с заменой текущих столбцов Payment на столбцы, в которых первый столбец (Payment_1) представляет значение в столбце Start_Year, а столбцы последовательно идут оттуда. Например, я хотел бы, чтобы таблица выше выглядела так:

ID    Start_Year    Payment_1    Payment_2    Payment_3    Payment_4
 1          2010           19           15           NA           11
 2          2012           26           23           NA           NA
 3          2012           NA           05           NA           NA   
 4          2011           NA           14           NA           NA    

Таким образом, любая Платежная информация в первой таблице, которая выпадает до начала года, может быть отклонена. Если информация о платеже недоступна, значение должно быть NULL или NA (не ноль, так как они отличаются от NA в моих данных).

Я начал с попытки использовать динамический SQL для создания новых столбцов на основе столбца Start_year, но застрял. Я стал ближе, используя команды распространения и сбора из пакета dplyr в R, но мой канал продолжает работать неправильно, и я не могу найти способ отбросить информацию об Оплате, которая предшествует значению start_year.

Любая помощь высоко ценится, большое спасибо заранее.

(Я понимаю, что это странный формат, в котором нужно хранить данные, но это то, что мне нужно сделать).

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Схожая идея с ответом @ Райана, но только с tidyervse:

library(tidyverse)

df %>%
  gather(Payment, value, -c(ID:Start_Year)) %>%
  filter(sub("Payment_", "", Payment) >= Start_Year) %>%
  group_by(ID) %>%
  mutate(Payment = seq(n())) %>%
  spread(Payment, value, sep = "_")

Результат:

# A tibble: 4 x 6
# Groups:   ID [4]
     ID Start_Year Payment_1 Payment_2 Payment_3 Payment_4
  <int>      <int>     <int>     <int>     <int>     <int>
1     1       2010        19        15        NA        11
2     2       2012        26        23        NA        NA
3     3       2012        NA         5        NA        NA
4     4       2011        NA        14        NA        NA

Данные:

df < -structure(list(ID = 1:4, Start_Year = c(2010L, 2012L, 2012L, 
2011L), Payment_2010 = c(19L, 22L, NA, 17L), Payment_2011 = c(15L, 
24L, NA, NA), Payment_2012 = c(NA, 26L, NA, 14L), Payment_2013 = c(11L, 
23L, 5L, NA)), .Names = c("ID", "Start_Year", "Payment_2010", 
"Payment_2011", "Payment_2012", "Payment_2013"), class = "data.frame", row.names = c(NA, 
-4L))
0 голосов
/ 29 августа 2018

Использование data.table::shift для удаления предыдущих лет:

library(data.table)
dt <- fread("ID    Start_Year    Payment_2010    Payment_2011    Payment_2012    Payment_2013
 1          2010              19              15              NA              11
 2          2012              22              24              26              23
 3          2012              NA              NA              NA              05   
 4          2011              17              NA              14              NA")

dtans <- dcast(
    melt(dt, id.vars=c("ID", "Start_Year"))[, 
        value := shift(value, grep(Start_Year[1L], variable) - 1L, type="lead"), by=.(ID)],
    ID + Start_Year ~ variable)

#label columns according to OP
cols <- grep("^Payment", names(dtans), value=TRUE)
setnames(dtans, cols, paste0("Payment_", seq_len(length(cols)))) 
dtans

Выход:

   ID Start_Year Payment_1 Payment_2 Payment_3 Payment_4
1:  1       2010        19        15        NA        11
2:  2       2012        26        23        NA        NA
3:  3       2012        NA         5        NA        NA
4:  4       2011        NA        14        NA        NA

Или с использованием базы R без преобразования данных в длинный формат:

mat <- read.table(text="ID    Start_Year    Payment_2010    Payment_2011    Payment_2012    Payment_2013
 1          2010              19              15              NA              11
 2          2012              22              24              26              23
 3          2012              NA              NA              NA              05   
 4          2011              17              NA              14              NA", header=TRUE)
ans <- t(apply(mat, 1, function(x) {
    n <- grep(x["Start_Year"], names(mat)) - 1L
    c(x[1:2], x[-seq_len(n)], rep(NA_integer_, n - 2L))
}))

#label rows and columns according to OP
rownames(ans) <- rownames(mat)
colnames(ans) <- c(colnames(mat)[1:2], paste0("Payment_", seq_len(ncol(mat)-2)))
ans

выход:

  ID Start_Year Payment_1 Payment_2 Payment_3 Payment_4
1  1       2010        19        15        NA        11
2  2       2012        26        23        NA        NA
3  3       2012        NA         5        NA        NA
4  4       2011        NA        14        NA        NA
0 голосов
/ 28 августа 2018
library(tidyverse)
library(data.table) # or reshape2

df %>% 
  melt(c('ID', 'Start_Year')) %>% 
  mutate(variable = as.numeric(gsub('Payment_', '', variable)) - Start_Year + 1) %>% 
  filter(variable >= 1) %>% 
  dcast(ID + Start_Year ~ variable) %>% 
  rename_at(vars(-ID, -Start_Year), ~paste0("Payment_", .)) #credit @avid_useR

#   ID Start_Year Payment_1 Payment_2 Payment_3 Payment_4
# 1  1       2010        19        15        NA        11
# 2  2       2012        26        23        NA        NA
# 3  3       2012        NA         5        NA        NA
# 4  4       2011        NA        14        NA        NA

Используемые данные:

structure(list(ID = 1:4, Start_Year = c(2010L, 2012L, 2012L, 
2011L), Payment_2010 = c(19L, 22L, NA, 17L), Payment_2011 = c(15L, 
24L, NA, NA), Payment_2012 = c(NA, 26L, NA, 14L), Payment_2013 = c(11L, 
23L, 5L, NA)), .Names = c("ID", "Start_Year", "Payment_2010", 
"Payment_2011", "Payment_2012", "Payment_2013"), row.names = c(NA, 
-4L), class = "data.frame")
...