全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 R语言论坛
5902 14
2015-02-26
《R语言实战》书中代码清单7-15如下:
> table2flat<-function(mytable) {
+     df <- as.data.frame(mytable)
+     rows <- dim(df)[1]
+     cols <- dim(df)[2]
+     x <- NULL
+     for (i in 1:rows){
+         for (j in 1:df$Freq[i]){
+             row <- df[i,c(1:(cols-1))]
+             x <- rbind(x,row)
+         }
+     }
+     row.names(x)<-c(1:dim(x)[1])
+     return(x)
+ }
treatment <- rep(c("Placebo", "Treated"), times=3)
improved <- rep(c("None", "Some", "Marked"), each=2)
Freq <- c(29,13,7,17,7,21)
mytable <- as.data.frame(cbind(treatment, improved, Freq))
mytable
table2flat(mytable)
mytable

--------------------------------------------------------------
以下是输出结果:
> mytable
  treatment improved Freq
1   Placebo     None   29
2   Treated     None   13
3   Placebo     Some    7
4   Treated     Some   17
5   Placebo   Marked    7
6   Treated   Marked   21
> table2flat(mytable)
   treatment improved
1    Placebo     None
2    Placebo     None
3    Placebo     None
4    Placebo     None
5    Treated     None
6    Placebo     Some
7    Placebo     Some
8    Placebo     Some
9    Placebo     Some
10   Placebo     Some
11   Treated     Some
12   Treated     Some
13   Placebo   Marked
14   Placebo   Marked
15   Placebo   Marked
16   Placebo   Marked
17   Placebo   Marked
18   Treated   Marked
19   Treated   Marked
20   Treated   Marked
> mytable
  treatment improved Freq
1   Placebo     None   29
2   Treated     None   13
3   Placebo     Some    7
4   Treated     Some   17
5   Placebo   Marked    7
6   Treated   Marked   21
问题:table2flat(mytable)的结果应该是94条记录,为什么执行结果是20条记录?

由此可以看出:以上书中代码7-15是错误的,把for (j in 1:df$Freq[i])改成 for (j in 1:as.integer(as.character((df$Freq[i]))))就可以了。
这里有一个细节,需要理解R中factor类型,factor类型在R内部存储时候是level值(整数),level值的factor类型直接转化成numeric或者integer都将导致错误把level值(整数)转出数值,与想要的结果不符,应该是先转成character再转成integer。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2015-2-26 13:08:07
构建mytable 的时候用这个:
mytable <- data.frame(treatment, improved, Freq)

因为你构建的时候用的是cbind, cbind生成类型为matrix, 意味着里面所有数据类型一样
在此情况下,你的treatment,improved,和Freq的类型转成一样了(在这里是character)
然后转为data.frame的时候character被自动转为factor

所以当读到每一行的Freq, 数量就不一样了。比如说读到29是因子的labels, 但实际levels29对应的只是4
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2015-2-26 15:01:57
赫赫,谢谢交流。你是从为什么mytable的Freq列是一个factor的角度来分析这个结果,并提到了关于Matrix的一个知识细节,很好!关于factor和matrix的两个知识细节以及编写自定义函数时对自变量类型需要特别关注,在这里都体现了。

通过该例子尤其启发我们:做自定义函数时,要提前想清楚该函数的自变量类型,对于不同类型自变量,处理方式是不同的。自定义函数的代码尽量要有扩展性和通用性,能对自变量是matrix和dataframe以及其它类型都能正确处理。

再举个例子,还是这本书,在代码清单7-7中:
dstats<-function(x) (c(mean=mean(x),sd=sd(x)))
by(mtcars[vars],mtcars$am,dstats)

以上代码运行时会提示错误,稍微分析看出:dstats的自变量是类型为dataframe的mtcars[vars],而mean函数和sd函数自变量不能是dataframe类型:

> str(mtcars[vars])'data.frame':        32 obs. of  3 variables: $ mpg: num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ... $ hp : num  110 110 93 110 175 105 245 62 95 123 ... $ wt : num  2.62 2.88 2.32 3.21 3.44 ...
解决办法:修改自定义函数dstats如下,可以得到正确结果。

> dstats<-function(x)(c(mean=apply(x,2,mean),sd=apply(x,2,sd)))> by(mtcars[vars],mtcars$am,dstats)mtcars$am: 0   mean.mpg     mean.hp     mean.wt      sd.mpg       sd.hp       sd.wt  17.1473684 160.2631579   3.7688947   3.8339664  53.9081957   0.7774001 ------------------------------------------------------- mtcars$am: 1   mean.mpg     mean.hp     mean.wt      sd.mpg       sd.hp       sd.wt  24.3923077 126.8461538   2.4110000   6.1665038  84.0623243   0.6169816

>

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2015-3-14 14:02:24
按 mytable <- data.frame(treatment, improved, Freq) 去编译结果是正确的,谢谢!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2015-4-13 08:59:37
谢谢分享
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2016-1-24 20:24:19
for (j in 1:dfFreq[i]){

书中这里也是有问题的,如果Freq[i]返回的只有0,如:for(j in 1:0) print("haha"),还是会返回两个haha的!!!,这样就多返回了两行,其实这两行是并不存在的!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群