Ниже приведен небольшой набор данных о транзакциях с идентификатором, датой месяца, фиктивной переменной Bad_Credit или без нее. Я хотел бы вытащить все транзакции после начала плохой кредитной истории. В столбце OUTPUT указан правильный результат, то есть строки 1,2,3,5,6,8,10.
Это просто пример, может быть тысячи строк. SQL, R, SPSS будут работать. Спасибо.
Кто-нибудь знает, как использовать SPSS, чтобы сделать это?


Если я правильно понимаю, вы можете использовать оконные функции:
select t.*
from (select t.*,
min(case when bad_credit = 1 then date end) over (partition by id) as min_bd_date
from t
) t
where date >= min_bd_date;
Вы также можете сделать это с помощью коррелированного подзапроса:
select t.*
from t
where t.date >= (select min(t2.date)
from t t2
where t2.id = t.id and
t2.bad_credit = 1
);
Спасибо. Прекрасно работает.
@ГанРен. . . Есть ли причина, по которой вы не приняли ответ?
Если это в базе данных, то я думаю, что SQL, вероятно, лучше всего подходит для решения этой проблемы. Однако, если он у вас уже есть в R, то...
Вот метод R, использующий dplyr:
library(dplyr)
dat %>%
group_by(ID) %>%
mutate(OUTPUT2 = +cumany(Bad_CREDIT)) %>%
ungroup()
# # A tibble: 10 x 5
# DATE ID Bad_CREDIT OUTPUT OUTPUT2
# <int> <chr> <int> <int> <int>
# 1 12 A 1 1 1
# 2 15 A 1 1 1
# 3 18 A 0 1 1
# 4 2 B 0 0 0
# 5 10 B 1 1 1
# 6 20 B 0 1 1
# 7 5 C 0 0 0
# 8 15 C 1 1 1
# 9 1 D 0 0 0
# 10 9 E 1 1 1
Поскольку это фактически простая операция группировки, то базовые решения R и data.table столь же просты.
+ave(dat$Bad_CREDIT, dat$ID, FUN=cumany)
# [1] 1 1 1 0 1 1 0 1 0 1
library(data.table)
datDT <- as.data.table(dat)
datDT[, OUTPUT2 := +cumany(Bad_CREDIT), by = .(ID)]
Спасибо. Я не силен в dplyr, использую только sqldf :)
Вы можете arrange данные с помощью ID и DATE и для каждого ID присвоить 0, если первое значение Bad_CREDIT равно 0.
library(dplyr)
df %>%
arrange(ID, DATE) %>%
group_by(ID) %>%
mutate(OUTPUT = as.integer(!(first(Bad_CREDIT) == 0 & row_number() == 1)))
# DATE ID Bad_CREDIT OUTPUT
# <int> <chr> <int> <int>
# 1 12 A 1 1
# 2 15 A 1 1
# 3 18 A 0 1
# 4 2 B 0 0
# 5 10 B 1 1
# 6 20 B 0 1
# 7 5 C 0 0
# 8 15 C 1 1
# 9 1 D 0 0
#10 9 E 1 1
данные
df <- structure(list(DATE = c(12L, 15L, 18L, 2L, 10L, 20L, 5L, 15L,
1L, 9L), ID = c("A", "A", "A", "B", "B", "B", "C", "C", "D",
"E"), Bad_CREDIT = c(1L, 1L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 1L)),
row.names = c(NA, -10L), class = "data.frame")
Спасибо. Я не силен в dplyr, использую только sqldf :)
Вы можете использовать EXISTS следующим образом:
select t.* from your_table t
where exists
(select 1
from your_table tt
where t.id = tt.id
and t.date >= tt.date
and tt.bad_credit = 1);
Спасибо, очень ценю это.
Это для SPSS:
sort cases by ID date.
compute PullOut=Bad_CREDIT.
if $casenum>1 and ID=lag(ID) and lag(PullOut)=1 PullOut=1.
exe.
Кстати, плохая кредитная история не обязательно должна быть связана со второй транзакцией, это может быть третья или более поздняя...