发现不良信用后取消所有交易

Pull out all transactions after a bad credit found

下面是一个交易记录的小数据集,ID,月份日期,虚拟变量Bad_Credit与否。我想在信用不良开始后取消所有交易。 OUTPUT 列表示正确的结果,即第 1,2,3,5,6,8,10 行。

这只是一个示例,可能有数千行。 SQL, R, SPSS 都行。谢谢。

DATE ID Bad_CREDIT OUTPUT
12 A 1 1
15 A 1 1
18 A 0 1
2 B 0 0
10 B 1 1
20 B 0 1
5 C 0 0
15 C 1 1
1 D 0 0
9 E 1 1

如果我没理解错的话,你可以使用window函数:

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)]

您可以通过 IDDATE arrange 数据,如果 Bad_CREDIT 的第一个值为 0,则为每个 ID 分配 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")

您可以按如下方式使用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.