R data.table:将行设置为等于范围内的前一行

时间:2015-10-25 21:14:47

标签: r data.table

我正在尝试通过为其提供更好的分类标签来清理犯罪数据的数据集。该表的样本如下所示:

object getReq
{      
  def LeftError[B](str: String) = Left[HResponse, B](HttpError(str))
  def apply(line1: String, in: java.io.BufferedReader): Either[HResponse, HttpReq] = 
  {
    def loop(acc: Seq[(String, String)]): Either[HResponse, Seq[(String, String)]] =
    {
      val ln = in.readLine
      if (ln == "")
        Right(acc)         
      else
        ln.splitOut(':', s => LeftError("400 Bad Syntax in Header Field"), (a, b) => loop(acc :+ Tuple2(a.toLowerCase, b)))
    }

    val words: Seq[String] = line1.lowerWords

    for
    {
      a3 <- words match
      {
        case Seq("get", b, c) => Right[HResponse, (ReqType.Value, String, String)]((ReqType.HGet, b, c))
        case Seq("post", b, c) => Right[HResponse, (ReqType.Value, String, String)]((ReqType.HPost, b, c))
        case Seq(methodName, b, c) => LeftError("405" -- methodName -- "method not Allowed")
        case _ => LeftError("400 Bad Request: Bad Syntax in Status Line")
      }
      val (reqType, target, version) = a3
      fields <- loop(Nil)
      val optLen = fields.find(_._1 == "content-length")
      pair <- optLen match
      {
        case None => Right((0, fields))
        case Some(("content-length", second)) => second.filterNot(_.isWhitespace) match
        {
          case s if s.forall(_.isDigit) => Right((s.toInt, fields.filterNot(_._1 == "content-length")))
          case s => LeftError("400 Bad Request: Bad Content-Length SyntaxLine")
        }
      }
      val (bodyLen, otherHeaderPairs) = pair
      val otherHeaderFields = otherHeaderPairs.map(pair => HeaderField(pair._1, pair._2))
      val body = if (bodyLen > 0) (for (i <- 1 to bodyLen) yield in.read.toChar).mkString else ""         
    }      
    yield (HttpReq(reqType, target, version, otherHeaderFields, bodyLen, body))
  }   
}

正如您所看到的,在原始数据集中,更广泛的犯罪分类类别被格式化为带有NA代码的全大写标题(例如d <- as.data.table(read.csv('[filepath]')) print(d) Classifications ucr_ncic_code SOVEREIGNTY NA Treason 101 Treason Misprison 102 Espionage 103 Sabotage 104 Sedition 105 Selective Service 106 Sovereignty 199 MILITARY NA Military Desertion 201 Military 299 IMMIGRATION NA Illegal Entry 301 False Citizenship 302 Smuggling Aliens 303 Immigration 399 HOMICIDE NA Homicide Family-Gun 901 Homicide Family-Weapon 902 Homicide Nonfam-Gun 903 <TRUNCATED> )。我想要做的是重新格式化数据,以便这些标题是表中自己的分类列。

这是我最初的解决方案,我几乎可以肯定这不是最好的方法,但会产生预期的结果:

SOVEREIGNTY NA

利用data.table包进行格式更改有什么更好的方法?我猜测有更好的方法来复制单元格而不是我设计的for循环。

1 个答案:

答案 0 :(得分:1)

我会使用rleid,如下所示:

DT[ , category := Classifications[1L],
    by = ceiling(rleid(is.na(ucr_ncic_code)) / 2)]

关键是is.na(ucr_ncic_code)在每个块中的TRUEFALSE之间交替显示,因此每个奇数#rleid都是一个节头,每个偶数节头都是具体犯罪。当除以2时,我们可以通过四舍五入来对连续的整数进行配对(例如,3&amp; 4都被计为2)。

要删除部分标题,只需使用DT <- DT[!is.na(ucr_ncic_code)]

成功检查(受评论here启发)是运行以下一对测试:

DT[ , .(test1 = all(category == toupper(category)),
        test2 = any(Classifications == toupper(Classifications)))]

test1确保所有已分配的category确实如此(强制执行只有类别全部大写的规则)并且test2确保Classifications中没有其他对象{1}}全部大写。