• R语言
  • 请大家帮我看一下这个程序,写的有点发晕了,希望可以得到大家的点拨!谢谢

library(foreign)

setwd("E:/SAS data")#指定路径

a1<-list.files()

a1

[1] "final1csv" "final2csv" "final3csv"

"final4csv" "final5csv" "final6csv"#文件夹内共有6个数据集(模拟生成,均包含相同变量,其中变量y包含缺失数据)

for (x1 in a1) {

Rdata1<-read.csv(x1)

print(Rdata1)

} #读入这6个csv格式数据集

到现在为止运行没有任何问题,问题在下面的程序:

library(Amelia) #对Rdata1中这6个数据集的y用amelia这个包进行填补

for (x1 in a1) {

while(d==1) [s:16]#这一步有个问题,由于d是数据集中的二分类变量:0和1,我想用d=1的个体的数 据对y进行填补(用下面的amelia),而d=0的那些个体的全部数据都不用,但是输出时要保留。估计这句写得不对,因为提示错误了...(见底部)

Rdata1.out<-amelia(x=Rdata1,m=5,p2s=0,startvals=0,logs="y",

idvars = c("rho", "nu","Rnum","y0","d0","c","d","y1","rind"))

write.amelia(obj=Rdata1.out,file.stem="E:/Rdata/Rdata",format = "csv")#[s:16]这里存在个问题就是write.amelia输出的只有"final6csv"1个数据集的填补结果,但我想要的是这6个数据集的结果,请问这里应该怎么编写程序啊?

print(Rdata1.out)[s:16]还有这里也是只出来一个数据集的结果,怎么才能6个都出来

}

这段程序运行后出现:错误: 找不到对象'd'

这段程序最终想要的结果就是给每个数据集填补5次,这样每个数据集最后生成一个文件夹,共6个,每个夹子里面都有5个填补好的数据集(填补就是用amelia就解决了)

别嫌我啰嗦,主要也是希望尽量吧问题给大家解释清楚,可能有些问题有些简单,但我现在真是需要大家的帮助,非常感谢!

不知道这里有悬赏求助之类的方式吗,要不大家不是很愿意回答这种比较麻烦的程序问题

首先R不会智能的把数据累加或者合并起来,其次某个数据集中的某个变量可以用$符号调用,如Rdata$d。当然还有其他问题。。。

这一句,

for (x1 in a1) {<br />
    Rdata1 <- read.csv(x1)<br />
    print(Rdata1)<br />
}


每一次循环都把Rdata1覆盖掉了,合理的做法是将几个data.frame存到一个list中。
Rdata <- list()<br />
for (i in seq_along(a1)) {<br />
    Rdata[[i]] <- read.csv(a1[i])<br />
    print(Rdata[[i]])<br />
}


在后面的循环中,你应该把数据拆成d = 0d = 1的两部分,然后对d = 1的部分进行插补。

比如
Rdata.out <- list()<br />
for (i in seq_along(a1)) {<br />
    d1 <- subset(Rdata[[i]], d == 1)<br />
    d0 <- subset(Rdata[[i]], d == 0)<br />
    Rdata.out[[i]] <- amelia(x = d1, ...)<br />
    ...<br />
}
</p>

回复 第4楼 的 Ihavenothing:我也这么想过,可d=0的那部分数据怎么办,我最后输出的数据既需要d=1那部分填补后的数据,也需要d=0的那部分数据啊,两部分不分开的,因为最后要用模型分析整个数据集

回复 第4楼 的 Ihavenothing:不知道可以不可以用by函数来实现,我是这么写的

by(Rdata1,d,function(x) amelia(x=Rdata1,m=5,p2s=0,startvals=0,logs="y",

idvars = c("rho", "nu","Rnum","y0","d0","c","d","y1","rind"))),不过还是提示是d的问题,不知能否通过指定d,然后通过by来实现啊?

回复 第6楼 的 zjk0507:看起来好复杂,有木有试过rbind直接堆起来呢?

话说4楼回答的很清楚了,最后如果一起分析,7楼的方法也应该行得通。

回复 第7楼 的 波波头一头:是不是觉得amelia里面的复杂啊,其实就是by(Rdata1,d,function(x) amelia(x=Rdata1,m=5...)),rbind好像是连接两个矩阵的,但是怎么才能输出6个数据集的填补结果啊

回复 第7楼 的 波波头一头:

我用rind函数后总是提示:“错误于rbind(deparse.level, ...) : 串列参数有错:所有变数的长度都应该是一样的”这是我写的程序(前面的与4楼的一样):

...

Rdata.out[] <- amelia(x = d1, ...)

Rdata.imp[] <- rbind(Rdata.imp[],d0)

write.amelia(obj=Rdata.out[],file.stem="E:/Rdata/impute",format = "csv")

print(Rdata.out[])

}

请问这是怎么回事啊,应该如何解决呢


回复 第10楼 的 zjk0507:一种方法是你在你可以在subset之后直接rbind成列表:

<br />
Rdata.out <- list()<br />
d1=d0=NULL<br />
for (i in seq_along(a1)) {<br />
    d1 <- rbind(d1,subset(Rdata[[i]], d == 1))<br />
    d0 <- rbind(d0,subset(Rdata[[i]], d == 0))<br />
    Rdata.out <- amelia(x = d1, ...)<br />
    ...<br />
}<br />


或者最后一起来:
<br />
Rdata.out <- list()<br />
Rdata.rest <- list()<br />
for (i in seq_along(a1)) {<br />
    d1 <- subset(Rdata[[i]], d == 1)<br />
    Rdata.rest[[i]] <- subset(Rdata[[i]], d == 0)<br />
    Rdata.out[[i]] <- amelia(x = d1, ...)<br />
    ...<br />
}<br />
Rdata.imp <- rbind(do.call(rbind,Rdata.out),do.call(rbind,Rdata.rest))<br />


话说你的这句
<br />
Rdata.imp[[i]] <- rbind(Rdata.imp[[i]],d0)<br />


应该是
<br />
Rdata.imp[[i]] <- rbind(Rdata.out[[i]],d0)<br />


且应该在for循环中。

如果还是有同样错误应该是数据问题了。
</p>

回复 第11楼 的 suckbunny:非常感谢suckbunny的详细回答,我试了下你的程序发现几个问题:

首先是第一个方法,输出函数是:write.amelia(obj=Rdata.out,...)!

运行之后发现结果里还是没有d=0的个体数据,而且除了有d=1的个体数据以外,还有一些额外多出的d=1的个体数据,这些数据不知道从哪儿来的;

第二个方法,输出函数是:write.amelia(obj=Rdata.out[]...)!

运行之后,最后出现提示:错误于rbind(deparse.level, ...) : 变量的列数不对!这是怎么回事,没法rbind?好像是Rdata.imp <- rbind(do.call(rbind,Rdata.out),do.call(rbind,Rdata.rest))这句出现了问题!

最后一个共性问题是全部程序运行之后都只输出了一个数据集填补结果,没有输出其他数据集的结果,是write()不对吗?


这里先上传了我的两个数据集,数据应该是没有问题

也许是我自己没有说清楚我的意图:我做的是数据填补,再填补时我选择的填补次数是5次,例如对于第一个数据集final1,我们会针对该数据集里d=1个体中的所有缺失数据都填补5次,其他非缺失数据不变;这样final1就会产出5个填补好的数据集,然后这5个由final1得出填补数据集再分别加上相同的d=0个体的数据(也是final1中的)最后得出5个完整的数据集以备分析,以此类推final2,final3...我给出的例子是6个,其实这样的数据我模拟产生了100个...最后都得输出在文件夹中,因为我还要用其他的软件对这些数据进行分析,实在是没辙了,非常感谢大家!

回复 第15楼 的 zjk0507:话说你可以先传数据的一小部分上来,你的要求我也大致了解了。还是实战演练的好~

回复 第18楼 的 zjk0507:有数据就好搞了:(PS:水平有限可能烦了点)

<br />
trans <- function(filepath="E:/SAS data"){<br />
  setwd(filepath)<br />
  a1 <- list.files(pattern="*.csv")<br />
  Rdata1=Rdata2=list()<br />
  for (i in a1) {<br />
    Rdata1[[i]] <- subset(read.csv(i),d==1)<br />
    Rdata2[[i]] <- subset(read.csv(i),d==0)<br />
    #print(Rdata1)<br />
  }</p>
<p>  for(i in seq_along(a1)){<br />
    Rdata.out <- amelia(x=Rdata1[[i]],m=5,p2s=0,startvals=0,logs="y",<br />
                        idvars = c("rho", "nu","Rnum","y0","d0","c","d","y1","rind"))<br />
    for(j in 1:5){<br />
      write.csv(rbind(Rdata2[[i]],Rdata.out[[1]][[j]]),file=paste(c("Trans-final",i,"-               ",j,".csv"),collapse=''),row.names=F)<br />
    }<br />
  }<br />
}<br />


应该可以了。

应该有更简单的方法,代码有问题可以问我。[s:11]

主要是你Amelia后数据变成了列表,我不太擅长哈~
</p>

回复 第19楼 的 suckbunny:数据变成了列表是什么意思啊?有什么影响吗?