假设我有一个名为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
创建新名称?
感谢您的帮助,
答案 0 :(得分:0)
rbind
或rbind.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”。因此,如果我在解释数据方面或者更正示例输出时出错,请告诉我。