library(splm)
library(spdep)
library(rgdal)
library(spdep)
library(maptools)
library(foreign)
Open the shapefile of Counties that we need to create a stacked weight for in R.
Counties<- readOGR(".","USCounties")
## OGR data source with driver: ESRI Shapefile
## Source: ".", layer: "USCounties"
## with 3098 features
## It has 63 fields
# Plot polygons for inspection
plot(Counties)
First, check how many counties are in the datases. This is good practice to ensure you are getting all the data you were expecting.
length(Counties)
## [1] 3098
Next, we’ll need to work with the unique identifier for each county. If the data structure for the unique FIPS code is a factor, we’ll need to convert to numeric value. Once converted, we look at the first few records of our dataset to ensure we have all the data required before continuing. Because this is a spatial format, we look at the data attached only by using @data.
class(Counties$FIPS)
## [1] "factor"
Counties$RID <- as.numeric(Counties$FIPS)
head(Counties@data)
## AREA PERIMETER CO99_D00_ CO99_D00_I STATE COUNTY NAME
## 0 0.5623933 4.254051 115 114 27 077 Lake of the Woods
## 1 0.6839444 5.326881 116 115 53 073 Whatcom
## 2 1.6499787 8.658548 118 117 30 029 Flathead
## 3 1.1592117 5.614212 119 118 30 053 Lincoln
## 4 0.4048582 2.966526 120 119 16 021 Boundary
## 5 1.3342615 5.517993 121 120 30 005 Blaine
## LSAD LSAD_TRANS FIPS OID_ FIPS_1 PR_END0105 PS_END0609 PR_ANNUAL
## 0 06 County 27077 1315 27077 0.3895349 0.1918159 0.07790698
## 1 06 County 53073 2945 53073 0.4103035 0.3763109 0.08206070
## 2 06 County 30029 1575 30029 0.4277601 0.3227757 0.08555203
## 3 06 County 30053 1587 30053 0.3678284 0.3022063 0.07356568
## 4 06 County 16021 525 16021 0.2394958 0.2063291 0.04789916
## 5 06 County 30005 1563 30005 0.3296178 0.3384615 0.06592357
## PS_ANNUAL PR_AGE1 PS_AGE1 PR_AGE2 PS_AGE2 PR_AGE3 PS_AGE3 PR_FEM
## 0 0.04795396 0.4640 0.4595118 0.3020 0.2715360 0.1235 0.14200648 0.5155
## 1 0.09407773 0.4400 0.4438256 0.3060 0.2765459 0.1045 0.11622325 0.5435
## 2 0.08069392 0.4530 0.4694915 0.2830 0.2602371 0.0960 0.10413963 0.5275
## 3 0.07555156 0.4680 0.4886819 0.2320 0.2271315 0.0670 0.07359613 0.4675
## 4 0.05158228 0.4705 0.4727929 0.2585 0.2499296 0.0845 0.08360125 0.4780
## 5 0.08461538 0.4455 0.4067981 0.3195 0.3161429 0.1075 0.13512608 0.5295
## PS_FEM PR_BLACK PS_BLACK PR_ASIAN PS_ASIAN PR_HISP
## 0 0.5066785 0.0005 0.0020839751 1e-03 0.0010419875 0.0000
## 1 0.5315883 0.0055 0.0065378831 7e-03 0.0122226685 0.0045
## 2 0.5165479 0.0005 0.0008925455 2e-03 0.0018939789 0.0020
## 3 0.4709373 0.0010 0.0011291083 5e-04 0.0006805764 0.0010
## 4 0.4752317 0.0020 0.0019882538 1e-03 0.0007201697 0.0030
## 5 0.5410103 0.0020 0.0024332937 0e+00 0.0000000000 0.0000
## PS_HISPANI PR_AIAN PS_AIAN PR_DUAL PS_DUAL PR_POPDEN0 PS_POPDEN5
## 0 0.000000000 0.0040 0.005966745 0.0750 0.1807441 3.487303 3.296049
## 1 0.005520302 0.0150 0.017084961 0.0755 0.2264800 78.703168 87.368283
## 2 0.002041946 0.0085 0.011113559 0.0580 0.2040641 14.606920 16.187632
## 3 0.001361856 0.0080 0.009497411 0.0775 0.2655374 5.214151 5.172630
## 4 0.003792455 0.0080 0.007546442 0.0860 0.2596107 7.779754 8.177766
## 5 0.000000000 0.2630 0.293153795 0.1135 0.2412683 1.658472 1.564770
## PR_NENGLAN PS_NENGLAN PR_EGRADS PS_EGRADS PR_XMCARE PS_XMCARE PR_AVGPOV
## 0 0.065 0.06451613 0.045 0.04486423 0.1328685 0.140000 0.100333
## 1 0.162 0.16174402 0.082 0.12749533 0.1252266 0.135023 0.119000
## 2 0.079 0.07926829 0.061 0.08147579 0.1540154 0.162605 0.133333
## 3 0.000 0.00000000 0.028 0.03881279 0.1540154 0.162605 0.167667
## 4 0.067 0.06666667 0.066 0.05530254 0.1290082 0.137768 0.168667
## 5 0.033 0.03333333 0.029 0.04205607 0.1540154 0.162605 0.259000
## PS_AVGPOV PR_COMP01 PS_COMP06 PR_MCPE00 PS_MCPE05 PR_RCOD00
## 0 0.090000 0.011978945 0.000000000 0.0000000 0.050429185 0
## 1 0.124714 0.033712827 0.049683349 0.1396425 0.139701402 0
## 2 0.125286 0.022902898 0.020786949 0.0000000 0.007323325 0
## 3 0.183143 0.023203019 0.005174984 0.0000000 0.006114770 0
## 4 0.148571 0.004492105 0.000000000 0.1022032 0.090957447 0
## 5 0.238143 0.000000000 0.000000000 0.0000000 0.000000000 0
## PS_RCOD06 PR_MOVEDE PS_MOVEDL PR_XPOV00 PS_XPOV05 PR_XUNE00 PS_XUNE05
## 0 0 0.07951919 0.03215848 8.9 10.0 4.0 4.6
## 1 0 0.09787715 0.08880584 11.4 13.9 5.1 5.0
## 2 0 0.15837343 0.17086026 11.6 12.5 5.2 4.2
## 3 0 0.15655041 0.14110025 17.0 19.1 8.4 7.5
## 4 0 0.16189956 0.15215059 15.4 14.0 7.6 7.4
## 5 0 0.03997511 0.05570375 22.6 26.2 5.4 3.8
## PR_XUNI00 PS_XUNI05 PR_DEND01 PS_DEND06 FIPS2 POLY_ID Regime RID
## 0 13.1 18.5 25.946733 44.90969 27077 1 1 1316
## 1 14.4 17.0 7.829853 12.85676 53073 2 1 2946
## 2 14.7 19.0 10.787930 12.93828 30029 4 1 1576
## 3 18.0 20.6 26.402960 26.40296 30053 5 1 1588
## 4 20.2 17.9 15.988973 15.98897 16021 6 1 526
## 5 24.3 22.6 42.066288 36.30957 30005 7 0 1564
Here we create an index that is the length of the total number of counties we have. (Or more precisely, that is the length of all unique identifiers, which should be the same.) Check the length of the index to confirm it matches the total number of counties.
index<- seq.int(length(Counties$RID))
length(index)
## [1] 3098
First, generate a weight. Here we use the nb package to create a first-order queen contiguity weight for each county.
W_q1 <- poly2nb(Counties,queen=TRUE)
Check the length of the weight. This should equal the length of one time period, or the total rows of Counties we start with.
length(W_q1)
## [1] 3098
Convert the weight to a weight-list object.
wr<- nb2listw(W_q1)
Convert to a sparse matrix.
w1<- listw2dgCMatrix(wr)
Create time periods, and validate. Because we have two time periods here, the length should be twice the size of our original dataset.
time_id<- c("PR","PS")
tperiods <- length(time_id)
tperiods
## [1] 2
Calculate the Kronecker product using a sparse matrix with diagonal = tperiods.
I.T <- Diagonal(tperiods)
I.T
## 2 x 2 diagonal matrix of class "ddiMatrix"
## [,1] [,2]
## [1,] 1 .
## [2,] . 1
bigWmat <- kronecker(I.T,w1)
str(bigWmat)
## Formal class 'dgTMatrix' [package "Matrix"] with 6 slots
## ..@ i : int [1:36244] 16 30 42 7 31 3 26 43 49 60 ...
## ..@ j : int [1:36244] 0 0 0 1 1 2 2 2 2 2 ...
## ..@ Dim : int [1:2] 6196 6196
## ..@ Dimnames:List of 2
## .. ..$ : NULL
## .. ..$ : NULL
## ..@ x : num [1:36244] 0.25 0.25 0.111 0.143 0.25 ...
## ..@ factors : list()
Inspect the big Weights matrix produced. It should be 3098 counties x 2 time periods = 6196 wide and long.
head(bigWmat)
## 6 x 6196 sparse Matrix of class "dgTMatrix"
##
## [1,] . . . . . . . . . . . . . . . .
## [2,] . . . . . . . 0.5 . . . . . . . .
## [3,] . . . 0.1111111 . . . . . . . . . . . .
## [4,] . . 0.25 . 0.25 . . . . . . . . . . .
## [5,] . . . 0.3333333 . . . . . . . . . 0.3333333 . .
## [6,] . . . . . . . . . . 0.25 . . . 0.25 .
##
## [1,] 0.3333333 . . . . . . . . . . . . . 0.3333333 ......
## [2,] . . . . . . . . . . . . . . . ......
## [3,] . . . . . . . . . . 0.1111111 . . . . ......
## [4,] . . . . . . . . . . . . 0.2500000 . . ......
## [5,] . . . . . . . . . . . . 0.3333333 . . ......
## [6,] . . . . . . . . . . . . . . . ......
##
## .....suppressing columns in show(); maybe adjust 'options(max.print= *, width = *)'
## ..............................
Convert back to list weights object.
bigW <- mat2listw(bigWmat,style="W")
summary(bigW)
## Characteristics of weights list object:
## Neighbour list object:
## Number of regions: 6196
## Number of nonzero links: 36244
## Percentage nonzero weights: 0.09440898
## Average number of links: 5.84958
## Link number distribution:
##
## 1 2 3 4 5 6 7 8 9 10 11 13 14
## 42 82 180 564 1318 2136 1322 430 96 18 4 2 2
## 42 least connected regions:
## 45 49 51 99 282 827 855 938 1388 1484 1565 1595 1631 1655 1662 1723 1730 1786 1932 1968 1969 3143 3147 3149 3197 3380 3925 3953 4036 4486 4582 4663 4693 4729 4753 4760 4821 4828 4884 5030 5066 5067 with 1 link
## 2 most connected regions:
## 1563 4661 with 14 links
##
## Weights style: W
## Weights constants summary:
## n nn S0 S1 S2
## W 6196 38390416 6196 2227.779 25236.31
class(bigW)
## [1] "listw" "nb"
The stacked weight is ready for writing. Write to a .gal file for use in GeodaSpace.
write.nb.gal(bigW$n, "Counties_BigW.gal", oldstyle=FALSE)