Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

write listw to ArcGIS SWM dbf format #171

Merged
merged 9 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export(gabrielneigh, geary.test, geary, geary.mc, globalG.test, graph2nb,
knearneigh, knn2nb)

export(listw2sn, sn2listw, read.gwt2nb, write.sn2gwt,
read.swmdbf2listw, read_swm_dbf, write.sn2DBF,
read.swmdbf2listw, read_swm_dbf, write.swmdbf, write_swm_dbf, write.sn2DBF,
lm.LMtests, lm.RStests, SD.RStests,
lm.morantest, localG, localG_perm, localmoran, localmoran_perm, moran,
moran.test, moran.mc, moran.plot, localmoran.sad, lm.morantest.sad,
Expand Down
51 changes: 51 additions & 0 deletions R/read.gwt2nb.R
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ read.swmdbf2listw <- function(fn, region.id=NULL, style=NULL, zero.policy=NULL)
if (is.null(style)) {
style <- "M"
}

if (style == "M")
warning("style is M (missing); style should be set to a valid value")

Expand All @@ -215,6 +216,19 @@ read.swmdbf2listw <- function(fn, region.id=NULL, style=NULL, zero.policy=NULL)
if (requireNamespace("foreign", quietly=TRUE)) {
df <- try(foreign::read.dbf(fn, as.is=TRUE), silent=TRUE)
if (inherits(df, "try-error")) stop(df[1])
# a SWM table that is _imported_ into ArcGIS Pro does not use the
# leading empty `Field1`. If it is not present, add it for this
# function to continue as anticipated
dbf_names <- colnames(df)
nb_idx <- which(dbf_names == "NID")
# ensure that `NID` is provided
if (length(nb_idx) == 0) stop("Field `NID` not found in provided .dbf")
if (nb_idx == 2L) {
df <- cbind(
Field1 = rep(0, nrow(df)),
df
)
}
JosiahParry marked this conversation as resolved.
Show resolved Hide resolved
if (is.null(region.id)) {
rn <- range(c(df[,2], df[,3]))
region.id <- as.character(rn[1]:rn[2])
Expand Down Expand Up @@ -246,3 +260,40 @@ read.swmdbf2listw <- function(fn, region.id=NULL, style=NULL, zero.policy=NULL)
read_swm_dbf <- function(fn) {
read.swmdbf2listw(fn, style="B")
}

write.swmdbf <- function(listw, file, ind, region.id = attr(listw, "region.id")) {
stopifnot(
"`ind` must be a character scalar" = is.character(ind),
"`ind` must be a character scalar" = length(ind) == 1,
"`listw` must be a `listw` spatial weights matrix" = inherits(listw, "listw"),
"package foreign is required to write to dbf" = requireNamespace("foreign")
)

n <- length(listw$neighbours)

# Unsure if it is possible to not have region.id in current state
# of spdep, including in the event.
if (is.null(region.id)) {
warning("`region.id` not supplied. Using row positions.")
region.id <- as.character(1:n)
}

# create indices from indices to match length of neighbors
from <- region.id[rep.int(1:n, card(listw$neighbours))]
# flatten the neighbor ids
to <- region.id[unlist(listw$neighbours)]
# flatten the weights
weight <- unlist(listw$weights)
# construct a data frame from the flattened structure
res <- data.frame(from, to, weight)

# give appropriate column names. The first column must be
# the unique ID column
colnames(res) <- c(ind, "NID", "WEIGHT")
foreign::write.dbf(res, file)
invisible(res)
}

write_swm_dbf <- function(listw, file, ind, region.id = attr(listw, "region.id")) {
write.swmdbf(listw, file, ind, region.id)
}
5 changes: 5 additions & 0 deletions man/read.gwt2nb.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
\alias{read.dat2listw}
\alias{read.swmdbf2listw}
\alias{read_swm_dbf}
\alias{write.swmdbf}
\alias{write_swm_dbf}
\alias{write.sn2dat}
\alias{write.sn2DBF}
%- Also NEED an '\alias' for EACH other topic documented here.
Expand All @@ -19,12 +21,15 @@ read.dat2listw(file)
write.sn2dat(sn, file)
read.swmdbf2listw(fn, region.id=NULL, style=NULL, zero.policy=NULL)
read_swm_dbf(fn)
write.swmdbf(listw, file, ind, region.id = attr(listw, "region.id"))
write_swm_dbf(listw, file, ind, region.id = attr(listw, "region.id"))
write.sn2DBF(sn, file)
}
%- maybe also 'usage' for other objects documented here.
\arguments{
\item{file, fn}{name of file with weights data}
\item{region.id}{a character vector of region IDs - for ArcGIS SWM DBFs, the values must be character integers (only numbers not starting with zero)}
\item{listw}{a \code{listw} object}
\item{sn}{a \code{spatial.neighbour} object}
\item{shpfile}{character string: if not given Shapefile name taken from GWT file for this dataset}
\item{ind}{character string: region id indicator field name}
Expand Down
Loading