【发布时间】:2013-08-18 17:56:35
【问题描述】:
更新:为了回应关于代码可读性的非常合理的评论,我重新构建了代码块。
我正在尝试绘制科罗拉多州每个地区的人口普查数据,但遇到了一些我不知道如何解释的问题。 (shapefile 可以在here 找到,Summary File 1 的数据是通过Census API 提取的。)在与数据搏斗后,我成功地用以下代码绘制了总人口:
#Set theme for histograms
theme_hist <- list(theme(panel.grid.minor = element_blank(),
panel.grid.major = element_blank(),
panel.background = element_blank(),
plot.background = element_blank(),
panel.border = element_blank(),
plot.title = element_text(size=22)))
#Plot map
pop_dist<-ggplot(aes(x=long,y=lat,group=group,fill=as.numeric(tot_pop)),data=co_mapd) +
geom_polygon(colour='white',size=.2) +
coord_equal() +
theme_opts +
labs(title='Distribution of Population') +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC',
midpoint=median(as.numeric(co_mapd$tot_pop)))
#ggsave('co_tract_pop_2010_map.png')
#Plot histogram
pop_hist<-ggplot(aes(x=as.numeric(tot_pop),group=group,fill=as.numeric(tot_pop)),data=co_mapd) +
geom_histogram() +
theme_hist +
xlab('Population Bins') +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC',
midpoint=median(as.numeric(co_mapd$tot_pop)))
#ggsave('co_tract_pop_2010_hist.png')
#Throw plots on a single canvas
grid.arrange(pop_dist,pop_hist)
这生成了下面的地图和直方图:
我认为这非常适合我想要做的事情,但我还有更多变数。一个函数会很有用。所以,这是我的功能:
map_var<-function(data,var,ttl){
dist<-ggplot(aes(x=long,y=lat,group=group,fill=var),data=data) +
geom_polygon(colour='white',size=.2) +
coord_equal() +
theme_opts +
labs(title=ttl) +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC',
midpoint=median(data$var))
hist<-ggplot(aes(x=var,group=group,fill=var),data=data) +
geom_histogram() +
theme_hist +
xlab('Bins') +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC',
midpoint=median(data$var))
grid.arrange(dist,hist)
}
map_var(co_mapd,tot_pop,'Distribution of Population')
似乎它应该可以工作,因为我试图准确地反映我在函数包装器之外所做的事情。我从字面上复制和粘贴,只是更改了函数参数发挥作用的元素。但是,它最终会引发以下错误:
Error in data.frame(x = c(-107.48212, -107.482115, -107.482062, -107.48206, :
arguments imply differing number of rows: 748351, 0
我还应该提到,在通过函数运行它之前,我将所有相关列转换为数字,因为函数中的 as.numeric() 给了我一些问题。
无论如何,我不清楚为什么参数会暗示函数中的行数不同,但在绘图代码独立时则不然。这让我觉得访问适当的环境正在发生一些时髦的事情,但我不确定是什么。任何帮助将不胜感激。
更新:我还尝试了 aes_string 路线(我以前不知道,所以谢谢你)。要么这不是问题,要么我误用了这项技术。
map_var<-function(data,var,ttl,coord_x,coord_y,group='group'){
dist<-ggplot(aes_string(x=coord_x,y=coord_y,group=group,fill=var),data=data) +
geom_polygon(colour='white',size=.2) +
coord_equal() +
theme_opts +
labs(title=ttl) +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC')
hist<-ggplot(aes(x=var,group=group,fill=var),data=data) +
geom_histogram() +
theme_hist +
xlab('Bins') +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC')
grid.arrange(dist,hist)
}
map_var(co_mapd,var='tot_pop',ttl='Distribution of Population',coord_x='long',coord_y='lat')
此版本抛出以下异常...
Don't know how to automatically pick scale for object of type function. Defaulting to continuous
Error in data.frame(x = function (x, y = NULL, na.rm = FALSE, use) :
arguments imply differing number of rows: 0, 748351
我仍然不清楚我使用的哪个参数意味着除了完整的 data.frame 之外的任何内容(除了不清楚为什么它只在函数内部很重要)。
更新 (8/20):我正在添加一个更新的代码块以包含 eval() 建议。
map_var<-function(data,var,ttl,coord_x,coord_y,group='group'){
dist<-ggplot(aes_string(x=eval(coord_x),y=eval(coord_y),group=eval(group),fill=eval(var)),data=data) +
geom_polygon(colour='white',size=.2) +
coord_equal() +
theme_opts +
labs(title=eval(ttl)) +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC')
hist<-ggplot(aes(x=eval(var),group=eval(group),fill=eval(var)),data=data) +
geom_histogram() +
theme_hist +
xlab('Bins') +
scale_fill_gradient2(low='#ECE7F2',mid='#A6BDDB',high='#3300CC')
grid.arrange(dist,hist)
}
map_var(co_mapd,var='tot_pop',ttl='Distribution of Population',coord_x='long',coord_y='lat')
我想明确分享,以防我执行不佳。但是,恐怕它并没有改变异常。
【问题讨论】:
-
尝试在你的函数中使用
aes_string(当然还要传递字符串给它)。 -
不错的代码,但很难阅读。请参阅google-styleguide.googlecode.com/svn/trunk/Rguide.xml 获取有关如何编写更清晰代码的指南,这在征求反馈时非常重要。考虑在
+符号后换行以确保易读性。有时,我什至会在每个新参数(,之后)处换行。 -
您仍然需要传递
aes_string()字符。您发布的代码有,例如,aes_string(x = coord_x)。这需要更改为aes_string(x = 'coord_x')。 -
我没有通过函数调用中的字符串(最后一行)来满足这个要求吗?
-
是和不是。如果你想传递这样的字符串,你需要在 eval 中包装 coord_x 等。所以例如
map_var的第一行应该是aes_string(x = eval(coord_x), ...