0

假设我有一个名为的数据表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)如果不存在这样的函数,我如何为array每次我的 for 循环到达新的数字记录时创建一个新名称?

谢谢你的帮助,

4

2 回答 2

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”。因此,让我知道我在解释数据或纠正示例输出的方式上是否有误。

于 2014-06-09T15:42:14.220 回答
0

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

df[nrow(df) + 1,] <- newrow
于 2014-06-09T14:37:44.870 回答