【问题标题】:How to remove rows after a particular observation is seen for the first time第一次看到特定观察后如何删除行
【发布时间】:2018-06-21 13:04:05
【问题描述】:

我有一个数据集,其中我有帐号和每次观察的“逾期天数”。对于每个帐号,只要“逾期天数”列达到“DLQ3”之类的代码,我就想删除该帐户的其余行(即使 DLQ3 是该帐户的第一个观察值)。

我的数据集如下所示:

Obs_month  Acc_No       OS_Bal      Days_past_due
201005     2000000031   3572.68     NORM
201006     2000000031   4036.78     NORM
200810     2000000049   39741.97    NORM
200811     2000000049   38437.54    DLQ3
200812     2000000049   23923.98    DLQ1
200901     2000000049   35063.88    NORM

因此,对于帐户 2000000049,我想删除日期为 200812 之后的所有行,因为它现在是默认设置。

总而言之,我想查看帐户何时达到 DLQ3 以及何时删除第一次 DLQ3 观察后的所有行。

我尝试使用所有 DLQ3 观察值对数据进行子集化,并按升序对观察月份进行排序,并获得一个唯一的帐号列表,其中包含 DLQ3 及其达到 DLQ3 的第一个月。发布我认为我可以用原始数据做一些 left_join 并使用 ifelse 但流程是冒险的。

【问题讨论】:

  • 你能缩进你的数据集吗?很难理解它的结构。 (突出显示数据,在 Mac 上按命令 K)
  • 现在缩进了。

标签: r database bigdata data-modeling finance


【解决方案1】:

以下函数将扫描您的数据框并找到包含 DLQ3 标记的行。然后,它将删除该标签之后出现的该帐号的所有行。

scan_table <- function(data_frame, due_column, acct_column, due_tag) {
    for(i in 1:nrow(data_frame)) {
        if(data_frame[i,c(due_column)] == due_tag) {
            # remove rows past here, for this account 
            acct_num <- data_frame[i,c(acct_column)]
            top_frame <- data_frame[1:i,] # cut point
            sub_frame <- subset(data_frame, Acc_No != acct_num)
            final_frame <- unique(do.call('rbind', list(top_frame, sub_frame)))
            return(final_frame)
        }
    }
}

示例

df

用法:

scan_table(df, 'Days_past_due', 'Acc_No', 'DLQ3')

如果您想要不同的东西,请告诉我。

【讨论】:

  • 在子框架行中,为什么帐号名称发生了变化?您是否认为它们的书写方式不同?
  • 子框架行从数据集中删除有问题的帐号。不知道你说的改名是什么意思。
【解决方案2】:

举个例子

data <- read.table(text=
"Obs_month  Acc_No       OS_Bal      Days_past_due
201005     2000000031   3572.68     NORM
201006     2000000031   4036.78     NORM
200810     2000000049   39741.97    NORM
200811     2000000049   38437.54    DLQ3
200812     2000000049   23923.98    DLQ1
200901     2000000049   35063.88    NORM", stringsAsFactors=F, header=T)

我会整理的

data <- data[with(data, order(Acc_No, Obs_month)), ]

并定义一个函数,允许您设置指示到期的代码(示例中的“DLQ3”或“DLQ1”)

sbst <- function(data, pattern){
  if( all(data$Days_past_due %in% "NORM") == TRUE){
    return(data)} else{
      indx <- min(grep(1, match(data$Days_past_due, pattern, nomatch = 0)))
      data <- data[1:indx,]
      return(data)
    }
}

最后,应用函数并将data.frame的列表聚合到最终的data.frame中

Reduce(rbind, lapply(split(data, data$Acc_No), sbst, patter="DLQ3"))
#  Obs_month     Acc_No   OS_Bal Days_past_due
#1    201005 2000000031  3572.68          NORM
#2    201006 2000000031  4036.78          NORM
#3    200810 2000000049 39741.97          NORM
#4    200811 2000000049 38437.54          DLQ3

【讨论】:

  • 这种方式会抛出一个错误,称为:匹配错误(数据$Days_past_due,模式,nomatch = 0):缺少参数“模式”,没有默认调用:grep(1,匹配(数据$Days_past_due, 模式, nomatch = 0))
  • 模式声明丢失patter="DLQ3",添加它,谢谢通知
  • 如果我理解您的编码,但由于我的原因出现错误。逾期天数有4个类别,分别是NORM、DLQ1、DLQ2、DLQ3。代码只处理NORM?
  • 我认为 NORM 表示 OK,表示未到期,因此只有 DLQ1、DLQ2、DLQ3 等其他值。可能是到期的迹象。我的假设正确吗?
  • 账号第一次达到DLQ3的点,表示他处于默认状态。因此,一个帐户可以拥有所有 4 个观察值,但我们需要删除它第一次达到 DLQ3 的那个
猜你喜欢
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多