关于资料整理,我很想推dplyr这个套件,
以及magrittr所导入的pipeline语法。
借你的问题来跟大家分享一下如何用dplyr来解决这种问题
: 各位大大好,小弟在做coursera的作业时有一题要求把
: 一个给定的data.frame(叫做airquality)中某两个向
: 量(Ozone和Temp)分别大于31和90时的第三个向量Solar.R
: 的平均值是多少?
```r
attach(airquality)
library(dplyr)
filter(airquality, !is.na(Ozone), !is.na(Temp)) %>%
filter(Ozone > 31, Temp > 90) %>%
`[[`("Solar.R") %>% mean
```
前两行加载资料和dplyr。
dplyr对于表格化的物件,如:
data.frame
data.table (当资料量大的时候,好用的套件)
SQL database 中的table
提供了一致的“动作”来作资料整理。
常用的有:
选行: select, 同SQL select
选列: filter, 同SQL where
排序: arrange, 同SQL sort by
取独特值: distinct, 同SQL distinct
更动值: mutate, 同SQL update
总结: summarise (可搭配group_by使用,类似SQL group by)
这里第三行
filter(airquality, !is.na(Ozone), !is.na(Temp))
表示从airquality中取出Ozone和Temp不是NA的列出来
第三行最后面的`%>%`是magrittr套件(dplyr会自动帮你加载它)
导入的一种`pipeline`方式的写法。
他的功能在于,把前面的输出结果,放到下一个函数的第一个参数
举例来说,原本我们要这样写:
df1 <- filter(airquality, !is.na(Ozone), !is.na(Temp))
df2 <- filter(df1, Ozone > 31, Temp > 90)
懒惰的人如我,可能会写成
filter(filter(airquality, !is.na(Ozone), !is.na(Temp)),
Ozone > 31, Temp > 90)
这样可以略过中间的暂存变量df1,但是程式码也变丑了
透过`%>%`,我们可以把上面两行改成:
filter(airquality, !is.na(Ozone), !is.na(Temp)) %>% # df1
filter(Ozone > 31, Temp > 90) # filter(df1, ...)
不但可以略过暂存变量,同时程式码仍然看起清楚
最后利用`%>%`和`[[`达到取出行变量Solar.R
再用mean算出平均值。
这里顺便跟大家宣导一个小概念:
R 中所有的东西都是“函数”,包含airquality[["Solar.R"]]这种语法,
实际上是`[[`(airquality, "Solar.R")
利用这样的概念,再搭配`%>%`的威力,程式码就写的更爽了
: 后来我有发现可以用:
: attach(data)
: sub <- subset(data,Ozone > 31 & Temp > 90)
: summary(sub)
: 的方式求出Solar.R在符合上述两个条件之下的平均值。
: 但一开始只是直觉地想要用for loop暴力算,但没成功,
: 想问板上是否可以用循环的方式算出来?以下是自己尝试
: 的程式码,附带一提:
: data[,1]是Ozone
: data[,2]是Solar.R
: data[,4]是Temp
: [程式范例]:
: add <- 0
: count <- 0
: for(i in 1:153){
: if(data[i,1]>31 & data[i,4]>90)
: add <- add + data[i,2] #把符合条件的Temp值累加
: count <- count + 1
: }
: mean <- add/count
: 这里遇到的问题是data[,1]含有NA值,所以我想把有NA值
: 的资料删掉,于是先跑这个for loop:
: for(i in 1:153){
: if(is.na(hw2[i,1]))
: hw2[i,] <- NULL
: }
: 结果:
: 错误在`[<-.data.frame`(`*tmp*`, i, , value = NULL) :
: replacement has 0 items, need 6
: 不知道是类型不一样,NULL不能随便套用还是其他原因,
: 总之先感谢各位大大把这篇看完QQ