楼主: hooli
6002 14

[学习分享] 对R in action(R语言实战)中代码7-15错误的纠正 [推广有奖]

  • 2关注
  • 3粉丝

已卖:340份资源

博士生

97%

还不是VIP/贵宾

-

威望
0
论坛币
26034 个
通用积分
2.2654
学术水平
88 点
热心指数
77 点
信用等级
47 点
经验
10596 点
帖子
148
精华
2
在线时间
328 小时
注册时间
2015-2-6
最后登录
2022-3-1

楼主
hooli 在职认证  发表于 2015-2-26 10:26:00 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
《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。
二维码

扫码加我 拉你入群

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

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

关键词:Action R语言实战 R语言 CTI ACT 中国 function action

沙发
jz.mraz 在职认证  发表于 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
已有 1 人评分论坛币 收起 理由
admin_kefu + 50 热心帮助其他会员

总评分: 论坛币 + 50   查看全部评分

藤椅
hooli 在职认证  发表于 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

>

板凳
lusiasue 发表于 2015-3-14 14:02:24
按 mytable <- data.frame(treatment, improved, Freq) 去编译结果是正确的,谢谢!

报纸
太阳出城 发表于 2015-4-13 08:59:37
谢谢分享

地板
dragonp 发表于 2016-1-24 20:24:19
for (j in 1:dfFreq[i]){

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

7
dragonp 发表于 2016-1-24 20:27:58
如果mytable是这样的话,
  1. > mytable2
  2.    Treatment Improved    Sex Freq
  3. 1    Placebo     None Female   19
  4. 2    Treated     None Female    6
  5. 3    Placebo     Some Female    7
  6. 4    Treated     Some Female    5
  7. 5    Placebo   Marked Female    6
  8. 6    Treated   Marked Female   16
  9. 7    Placebo     None   Male   10
  10. 8    Treated     None   Male    7
  11. 9    Placebo     Some   Male    0
  12. 10   Treated     Some   Male    2
  13. 11   Placebo   Marked   Male    1
  14. 12   Treated   Marked   Male    5
复制代码

8
nixuehua 发表于 2016-4-7 22:57:57
jz.mraz 发表于 2015-2-26 13:08
构建mytable 的时候用这个:
mytable
不好意思,请问一下,我按照您的代码改了,为什么出来了174行呢?

9
nixuehua 发表于 2016-4-7 22:58:29
lusiasue 发表于 2015-3-14 14:02
按 mytable
不好意思请问一下,我按照您的代码改了,为什么出来了174行呢?

10
nixuehua 发表于 2016-4-7 23:02:23
lusiasue 发表于 2015-3-14 14:02
按 mytable
不好意思,您的方法是正确的,我的自定义函数写错了,非常感谢!

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-30 13:16