【问题标题】:Running Analysis on Multiple geojson files对多个 geojson 文件运行分析
【发布时间】:2018-01-07 19:24:28
【问题描述】:

我有大约 113 个 geojson 文件,我以前主要在 QGIS 中处理过这些文件。我现在的目标是能够同时将所有文件导入 R 并对附加到每个相应层的基础属性表进行分析。我已经找到了导入一个文件并在转换为数据框后进行任何所需分析的最佳方法。我在文件夹中的文件都如下所示:0cfb16c1-90c2-412d-bb60-2fec34c75e9a.geojson

我用于这一步的代码是:

library(rgdal)
map1 <- readOGR(dsn = "/Users/chris/Documents/GeorgetownMPPMSFS/McCourtMPP/BIGWork/BIGDataFiles/maps/sampled_maps/0cfb16c1-90c2-412d-bb60-2fec34c75e9a.geojson", layer = "0cfb16c1-90c2-412d-bb60-2fec34c75e9a")
summary(map1)
map1 <- as.data.frame(map1)

我想在所有 geojson 文件上运行我在该地图上所做的相同分析,而不必一一进行。我进行的与选举重新划分指标相关的分析包括在此处:

cfbdata$reptotal <- (cfbdata$surveyed_republican_percentage/100)*cfbdata$surveyed_total
cfbdata$demtotal <- (cfbdata$surveyed_democrat_percentage/100)*cfbdata$surveyed_total
cfbdata$NAME <- NULL
aggdata <-aggregate(cfbdata, by=list(cfbdata$cluster), 
                    FUN=sum, na.rm=TRUE)
# Rep district victory is 1 and Dem district victory is 0
aggdata$result <- ifelse(aggdata$reptotal > aggdata$demtotal,1, ifelse(aggdata$demtotal > aggdata$reptotal,0, NA))

EffGapCalc <- subset(aggdata, select=c("cluster","reptotal","demtotal","surveyed_total", "result"))

# Step 1: Calculate Dem Wasted, Rep Wasted, and Net Wasted

EffGapCalc$repwasted <- ifelse(EffGapCalc$result == 1, EffGapCalc$reptotal - (.51*EffGapCalc$surveyed_total), ifelse(EffGapCalc$result == 0, EffGapCalc$reptotal, NA))

EffGapCalc$demwasted <- ifelse(EffGapCalc$result == 0, EffGapCalc$demtotal - (.51 * EffGapCalc$surveyed_total), ifelse(EffGapCalc$result == 1, EffGapCalc$demtotal, NA))

EffGapCalc$netwasted <- abs(EffGapCalc$repwasted - EffGapCalc$demwasted)

# Step 2: Sum Total Wasted Rep and Dem Votes
totrepwasted <- sum(EffGapCalc$repwasted)
totdemwasted <- sum(EffGapCalc$demwasted)
netwaste <- ifelse(totrepwasted>totdemwasted, totrepwasted-totdemwasted, ifelse(totrepwasted<totdemwasted, totdemwasted-totrepwasted))
netwaste
# Democrats had a net waste (more wasted votes) of 74289.6

# Step 3: Divide Net Wasted by Total Number of Votes Case
sum(EffGapCalc$surveyed_total)
totalsurvtot <- sum(EffGapCalc$surveyed_total)
netwaste/totalsurvtot
# Efficiency Gap = .0359 [3.60%]

目标是对所有 113 个 GEOJSON 文件运行相同的分析,并获得 113 个“效率差距”数字的列表,如上面的 .0359。

我在 stackoverflow 和其他地方搜索了许多问题,但没有找到合适的解决方案。虽然我最初认为 for 循环最适合这个,但根据我在其他地方读到的内容,lapply() 实际上可能是更好的选择。我面临的挑战是确保正确导入作为 'lapply()' 的一部分

我尝试使用失败的代码是:

library(rgdal)
fileNames <- list.files(path = "/Users/chris/Documents/GeorgetownMPPMSFS/McCourtMPP/BIGWork/BIGDataFiles/maps/sampled_maps", pattern="*.geojson", full.names = TRUE)

lapply(fileNames, function(x) {
  map1 <- readOGR(dsn = x, layer = x)
  map1 <- as.data.frame(map1)
  out <- map1$reptotal <- (map1$surveyed_republican_percentage/100)*map1$surveyed_total;
  map1$demtotal <- (map1$surveyed_democrat_percentage/100)*map1$surveyed_total;
  map1$NAME <- NULL;
  aggdata <-aggregate(map1, by=list(map1$cluster), 
                      FUN=sum, na.rm=TRUE);
  aggdata$result <- ifelse(aggdata$reptotal > aggdata$demtotal,1, ifelse(aggdata$demtotal > aggdata$reptotal,0, NA));

  EffGapCalc <- subset(aggdata, select=c("cluster","reptotal","demtotal","surveyed_total", "result"));
  # Step 1: Calculate Dem Wasted, Rep Wasted, and Net Wasted
  EffGapCalc$repwasted <- ifelse(EffGapCalc$result == 1, EffGapCalc$reptotal - (.51*EffGapCalc$surveyed_total), ifelse(EffGapCalc$result == 0, EffGapCalc$reptotal, NA));

  EffGapCalc$demwasted <- ifelse(EffGapCalc$result == 0, EffGapCalc$demtotal - (.51 * EffGapCalc$surveyed_total), ifelse(EffGapCalc$result == 1, EffGapCalc$demtotal, NA));

  EffGapCalc$netwasted <- abs(EffGapCalc$repwasted - EffGapCalc$demwasted);

  # Step 2: Sum Total Wasted Rep and Dem Votes
  totrepwasted <- sum(EffGapCalc$repwasted);
  totdemwasted <- sum(EffGapCalc$demwasted);
  netwaste <- ifelse(totrepwasted>totdemwasted, totrepwasted-totdemwasted, ifelse(totrepwasted<totdemwasted, totdemwasted-totrepwasted));
  netwaste

  # Step 3: Divide Net Wasted by Total Number of Votes Case
  totalsurvtot <- sum(EffGapCalc$surveyed_total);
  netwaste/totalsurvtot;

  write.table(out, "/Users/chris/Documents/GeorgetownMPPMSFS/McCourtMPP/BIGWork/BIGDataFiles", sep="\t", quote=F, row.names=F, col.names=T)
})

在这一点上,我已经尝试了两天来解决这个问题,但只会变得更加困惑。任何帮助将不胜感激!

【问题讨论】:

  • 你的最后一段代码是如何“失败”的?
  • 对不起。我应该澄清这一点。错误消息读取:ogrInfo 中的错误(dsn = dsn,层 = 层,编码 = 编码,use_iconv = use_iconv,:无法打开层调用自:ogrInfo(dsn = dsn,层 = 层,编码 = 编码,use_iconv = use_iconv, swapAxisOrder = swapAxisOrder, require_geomType = require_geomType)
  • 简化。从lapply 中的函数中删除所有内容并重新构建它。是第一行readOGR 造成的吗?您可以摆脱的无关代码越多越好。而且你应该一边写一边测试,而不是写了 30 行代码然后因为第一个有问题而碰壁。
  • 我怀疑它是因为您将 full 文件名传递给readOGR 作为 dsn 和图层参数,并且图层应该只是图层名称。如果不能轻松获取图层名称,请使用 DSN 上的ogrListLayers 获取。
  • 是的,我在没有其他代码的情况下运行它,它确实是导致问题的 readOGR 代码的第一部分。

标签: r for-loop gis geojson lapply


【解决方案1】:

简单的测试代码:

lapply(fileNames, function(x) {
  map1 <- readOGR(dsn = x, layer = x)
}

假设您的案例失败了,我们知道问题出在这一行。这使得这里的人更容易看到它是一个更简单的问题。请始终尝试尽量减少您的问题,这将帮助我们帮助您,并且在许多情况下它可以让您自己解决。进行中...

readOGR 对于 geoJSON 需要一个文件路径和一个图层名称,并且该代码将使用 geojson 包中的测试文件将文件路径作为图层名称提供,如下所示::

> testfile <- list.files(path = path, pattern="*.geojson", full.names = TRUE)[5]

快速检查我们已经得到它:

> file.exists(testfile)
[1] TRUE

然后尝试阅读:

> d = readOGR(dsn=testfile, layer=testfile)
Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv,  : 
  Cannot open layer

那么我们如何从文件路径中获取层名呢?为此我们有ogrListLayers

> ogrListLayers(testfile)
[1] "OGRGeoJSON"
attr(,"driver")
[1] "GeoJSON"
attr(,"nlayers")
[1] 1

现在看起来很奇怪,但它是图层名称和一些额外属性的向量,您可以为此忽略它们。此测试层的层名称为“OGRGeoJSON”。假设您的 geoJSON 仅是您可以执行的一层:

> d = readOGR(dsn=testfile, layer=ogrListLayers(testfile))
OGR data source with driver: GeoJSON 
Source: "/home/rowlings/R/x86_64-pc-linux-gnu-library/3.4/geojson/examples/linestring_one.geojson", layer: "OGRGeoJSON"
with 1 features
It has 2 fields
Warning message:
In readOGR(dsn = testfile, layer = ogrListLayers(testfile)) :
  Z-dimension discarded

现在我认为 geoJSON 只能有一层,或者 readOGR 默认为第一层,所以如果您知道 geoJSON 中只有一层,您可以省略 @ 987654331@ 参数并返回相同的对象:

> d2 = readOGR(dsn=testfile)
OGR data source with driver: GeoJSON 
Source: "/home/rowlings/R/x86_64-pc-linux-gnu-library/3.4/geojson/examples/linestring_one.geojson", layer: "OGRGeoJSON"
with 1 features
It has 2 fields
Warning message:
In readOGR(dsn = testfile) : Z-dimension discarded

【讨论】:

  • 感谢您的周到回复。看起来我仍然被图层部分所吸引。当 file.exists(testfile) 函数返回 true 时,ogrListLayers(testfile) 返回一个错误,显示 Error: length(dsn) == 1 is not TRUE。这里的完整代码是:testfile &lt;- list.files(path = "/Users/chris/Documents/GeorgetownMPPMSFS/McCourtMPP/BIGWork/BIGDataFiles/maps/sampled_maps", pattern="*.geojson", full.names = TRUE) file.exists(testfile) ogrListLayers(testfile)
  • 您在此处输入的内容会通过 allvector 与该模式匹配的 geoJSON 文件。在我的代码中,testfile 是一个 single geoJSON 文件。如果您看一下,您会看到它是该包中找到的文件的第 5 个 ([5]) 元素。
  • 对。是的,我知道如何使用单个 geoJSON 文件来执行此操作。我遇到的挑战是使用多个。我设法让 lapply 使用下面的代码遍历我的所有 113 个 geojson 文件,但最终只是覆盖了对象 113 次,而不是让自己能够对每个文件进行相同的分析。代码是:lapply(testfile, function(x) { map1 &lt;- readOGR(dsn = x, layer = ogrListLayers(x)) })
  • 现在将与map1 一起使用的代码添加到 lapply 中的函数中,就像您在问题中所做的那样,并在最后写一个表格。我们修复了一个错误...
  • 至少我不必传递单独的as.data.frame 函数。但是即使覆盖,我仍然无法在 lapply 中运行操作。包括我的代码的下一部分,我最近尝试的是:lapply(testfile, function(x) { map1 &lt;- readOGR(dsn = x, layer = ogrListLayers(x)) out &lt;- map1$reptotal &lt;- (map1$surveyed_republican_percentage/100)*map1$surveyed_total; map1$demtotal &lt;- (map1$surveyed_democrat_percentage/100)*map1$surveyed_total; })
猜你喜欢
  • 2021-10-30
  • 2020-09-11
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 2013-05-28
  • 2016-03-06
相关资源
最近更新 更多