在R中解析数据,替代rbind(),可以放入"用于"循环写行到新数据表?

时间:2014-06-09 14:12:18

标签: r parsing rbind

假设我有一个名为YC的数据表,如下所示:

Categories:           colsums:   tillTF:
ID: cat               NA         0 
  MA                  NA         0 
    spayed            NA         0
      declawed        NA         0 
        black         NA         0
          3           NA         0
            no        57         1
        claws         NA         0
          calico      NA         0
            4         NA         0
              no      42         1
           striped    NA         0
              0.5     NA         0
                yes   84         1
      not fixed       NA         0
         declawed     NA         0 
            black     NA         0 
              0.2     NA         0
                yes   19         1
              0.2     NA         0
                yes   104        1
  NH                  NA         0
    spayed            NA         0 
       claws          NA         0
          striped     NA         0
             12       NA         0 
               no     17         1
           black      NA         0
              4       NA         0
               yes    65         1
ID: DOG               NA         0 
 MA                   NA         0
...           

只有它1)实际上没有透视表,它的格式不一致看起来像一个和2)数据更加复杂,并且在几十年的过程中不断进入。可以安全地对数据做出的唯一假设是每个记录有12个变量,并且它们总是以相同的顺序输入。

我的目标是解析这些数据,以便每个属性和相关的数字记录都在一行的相应列中,如下所示:

Cat  MA  spayed    declawed  black    3    no  57
Cat  MA  spayed    claws     calico   0.5  no  42
Cat  MA  not fixed declawed  black    0.2  yes 19
Cat  MA  not fixed declawed  black    0.2  yes 104
Cat  NH  spayed    claws     striped  12   no  17
Cat  NH  spayed    claws     black    4    yes 65
Dog  MA ....

我编写了一个for循环,用于标识“记录”,然后通过向后读取数据表中的列直到达到另一个“记录”来重写数组中的值。我是R的新手,因此在不知道是否可能的情况下写下了我的理想循环。

array<-rep(0, length(7))
    for (i in 1:7)
      if(YC$tillTF[i]==1){
        array[7]<-(YC$colsums[i])
        array[6]<-(YC$Categories[i])
        array[5]<-(YC$Categories[i-1])
        array[4]<-(YC$Categories[i-2])
        array[3]<-(YC$Categories[i-3])
        array[2]<-(YC$Categories[i-4])
        array[1]<-(YC$Categories[i-5])
      }

    YC_NT<-rbind(array)

填写array后,我想循环浏览YC并在YC_NT为每条唯一记录创建一个新行:

for (i in 8:length(YC$tillTF))
  if (YC$tillTF[i]==1){
    array[8]<-(YC$colsums[i])
    array[7]<-(YC$Categories[i])
    if (YC$tillTF[i-1]==0){
      array[6]<-YC$Categories[i-1]
            }else{ 
              rbind(array, YC_NT)}
    if (YC$tillTF[i-2]==0){
      array[5]<-YC$Categories[i-2]
          }else{
            rbind(array, YC_NT)}
    if(YC$tillTF[i-3]==0){
      array[4]<-YC$Categories[i-3]
          }else{
            rbind(array, YC_NT)}
    if(YC$tillTF[i-4]==0){
      array[3]<-YC$Categories[i-4]
          }else{
            rbind(array, YC_NT)}
    if(YC$tillTF[i-5]==0){
      array[2]<-YC$Categories[i-5]
          }else{
            rbind(array, YC_NT)}
    if(YC$tillTF[i-6]==0){
      array[1]<-YC$Categories[i-6]
          }else{
            rbind(array, YC_NT)}
}else{ 
  array<-array}

当我在我的数据的函数中运行此循环时,我正在获取包含单行的YC_NT数据表。在搜索了几天后,我不知道有一个R函数可以将向量array添加到数据表的最后一行,而不是每次都给它一个唯一的名称。我的问题:

1)是否有一个函数可以将一个名为array的向量添加到数据表的末尾,而无需重写前一行array

2)如果不存在这样的函数,每当我的for循环到达新的数字记录时,如何为array创建新名称?

感谢您的帮助,

2 个答案:

答案 0 :(得分:0)

rbindrbind.fill应该可以解决问题。或者,您可以使用以下代码更有效地插入行:

df[nrow(df) + 1,] <- newrow

答案 1 :(得分:0)

所以我会假设每次tillTF=1开始新的记录。并且为下一个主题指定的n变量只是最后n个变量,之前的值都保持不变。我也假设所有记录都是“完整的”,因为最后一行是tillTF=1。 (为了使最后一个陈述成立,我从样本中删除了最后两行)

以下是我如何阅读

中的数据
dog <- read.fwf("dog.txt", widths=c(22,11,7), skip=1, stringsAsFactors=F)
dog$V1 <- gsub("\\s{2,}","",dog$V1)
dog$V2 < -gsub("\\s","",dog$V2)
dog$V3 <- as.numeric(gsub("\\s","",dog$V3))

所以我在这里阅读数据并剥去额外的空格。现在,我将添加一个ID列,为每条记录提供唯一的ID,并在每次tillTF=1时递增该值。然后我将分割该ID值的数据

dog$ID<-c(0, cumsum(dog$V3[-nrow(dog)]))
dv <- lapply(split(dog, dog$ID), function(x) {
    c(x$V1, x$V2[nrow(x)])}
)

现在,我将使用Reduce查看列表,并且每次使用n变量替换最后的n变量以获取给定ID。

trans < -Reduce(function(a,b) {
    a[(length(a)-length(b)+1):length(a)] <- b
    a
}, dv, accumulate=T)

现在我将所有数据与标签放在一起,然后使用read.table处理数据并进行所有正确的数据转换并创建数据框

dd<-read.table(text=sapply(a, paste0, collapse="\t"), sep="\t")

这给了

# print(dd)
       V1 V2        V3       V4      V5   V6  V7  V8
1 ID: cat MA    spayed declawed   black  3.0  no  57
2 ID: cat MA    spayed    claws  calico  4.0  no  42
3 ID: cat MA    spayed    claws striped  0.5 yes  84
4 ID: cat MA not fixed declawed   black  0.2 yes  19
5 ID: cat MA not fixed declawed   black  0.2 yes 104
6 ID: cat NH    spayed    claws striped 12.0  no  17
7 ID: cat NH    spayed    claws   black  4.0 yes  65

正如你所看到的那样,我留下了“ID:”,但它应该很容易将其剥离。但是这些命令会为您进行基本的重塑。解决方案中有更少的数组和if语句以及rbinding,这很好,但我建议您确保理解每一行,如果您想使用它。

另请注意,我的输出与预期输出略有不同;你错过了“84”的值,并将印有“42”的印花布列为“0.5”而不是“4.0”。因此,如果我在解释数据方面或者更正示例输出时出错,请告诉我。