在 R 中通过属性简单地对 SpatialPolygonsDataFrame 进行子集操作(即删除多边形)的方法

79

我想根据数据框@data中对应的属性值,从一个SpatialPolygonsDataFrame对象简单地删除一些多边形,以便可以绘制简化/子集形状文件。到目前为止,我还没有找到方法来实现这一点。

例如,假设我想要从这个世界形状文件中删除所有面积小于30000的多边形。我该如何操作呢?

或者,类似地,我如何删除南极洲?

require(maptools)

getinfo.shape("TM_WORLD_BORDERS_SIMPL-0.3.shp") 
# Shapefile type: Polygon, (5), # of Shapes: 246
world.map <- readShapeSpatial("TM_WORLD_BORDERS_SIMPL-0.3.shp")

class(world.map)
# [1] "SpatialPolygonsDataFrame"
# attr(,"package")
# [1] "sp"

head(world.map@data)
#   FIPS ISO2 ISO3 UN                NAME   AREA  POP2005 REGION SUBREGION     LON     LAT
# 0   AC   AG  ATG 28 Antigua and Barbuda     44    83039     19        29 -61.783  17.078
# 1   AG   DZ  DZA 12             Algeria 238174 32854159      2        15   2.632  28.163
# 2   AJ   AZ  AZE 31          Azerbaijan   8260  8352021    142       145  47.395  40.430
# 3   AL   AL  ALB  8             Albania   2740  3153731    150        39  20.068  41.143
# 4   AM   AM  ARM 51             Armenia   2820  3017661    142       145  44.563  40.534
# 5   AO   AO  AGO 24              Angola 124670 16095214      2        17  17.544 -12.296
如果我这样做,情节不会有任何变化。
world.map@data = world.map@data[world.map@data$AREA > 30000,]
plot(world.map)

如果我这样做,结果是一样的:

world.map@data = world.map@data[world.map@data$NAME != "Antarctica",]
plot(world.map)

非常感谢您的帮助!

5个回答

77

看起来你正在覆盖数据,但没有删除多边形。如果你想减少数据集,包括数据和多边形,请尝试使用:

看起来您正在覆盖数据,但未删除多边形。如果您想减小数据集,同时包括数据和多边形,请尝试使用:
world.map <- world.map[world.map$AREA > 30000,]
plot(world.map)

[[2016年4月19日编辑]] 那个解决方案曾经有效,但@Bonnie报告说对于新版本的R不再有效(尽管数据可能也有所改变): world.map <- world.map[world.map@data$AREA > 30000, ] 如果这有帮助,请给@Bonnie的答案点赞。


太简单了,但现在我知道了。谢谢! - baha-kev
1
正是我过去两天一直在努力解决的问题。谢谢! - chryss
两种解决方案(你的和Bonnie的)在我的R版本3.2.2中都有效。 - andschar

45

当我尝试在R 3.2.1中进行此操作时,Tim Riffe上面的技术对我无效,但稍微修改一下问题就可以解决。我发现我必须在指定要对其进行子集操作的属性之前,也要特别引用数据槽,如下所示:

world.map <- world.map[world.map@data$AREA > 30000, ]
plot(world.map)

如果其他人遇到相同的问题,可以将此作为另一种备选答案。


最新的R版本中,当我以这种方式对数据进行子集操作时,我的@data丢失了。Formal Class SpatialPolygonsDataFrame变成了Formal Class SpatialPolygons。你也遇到过这种情况吗? - Tim_Utrecht
这里也有同样的问题。你找到解决方案了吗? - severin
1
我没有使用过更新的R版本,但你可以尝试下面Erick Chacon的建议(使用subset)。 - Bonnie

17

只是提一下,subset也可以避免在条件中写入数据名称。

world.map <- subset(world.map, AREA > 30000)
plot(world.map)

是的,确切地说那个命令对我也没用。你还能用吗? - 5th
使用子集命令是我在并行环境(snowfall)下对空间数据进行子集的唯一方法。 - Lucas Fortini

12

我使用上述技巧制作了一个仅包含澳大利亚的地图:

australia.map < - world.map[world.map$NAME == "Australia",]
plot(australia.map)

事实证明,“Australia”后面的逗号很重要。

这种方法的一个缺点是,它似乎保留了所有其他国家的属性列和行,并仅用零填充它们。我发现如果我写出一个.shp文件,然后使用readOGR(rgdal软件包)读取它,它会自动删除空地理数据。然后我可以编写另一个仅包含所需数据的形状文件。

writeOGR(australia.map,".","australia",driver="ESRI Shapefile")
australia.map < - readOGR(".","australia")
writeOGR(australia.map,".","australia_small",driver="ESRI Shapefile")

在我的系统上,至少是“read”函数删除了null数据,因此我必须在读取一次文件后再将其写入(如果我尝试重新使用文件名,就会出现错误)。我相信有更简单的方法,但无论如何,这似乎足够满足我的需求。


2
正如此评论中所述,R不会自动删除未使用的因子水平,而是需要重新因子化:feature$ATTR <- factor(feature$ATTR) - a different ben
逗号很重要,因为它意味着一种选择:在逗号之前,我们选择行(所有名称等于澳大利亚的行),在逗号之后,我们选择列,在这里:选择所有列,因为没有指定特定的列。 - Richard
@adifferentben,droplevels() 不是更好的选择吗? - Nicola Pasquino

1
作为第二个指针:这对于具有形状“孔”的shapefile无效,因为它是按索引进行子集划分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接