Search code examples
rreport

Convert multiple moran.test outputs into structured, storable, copy-pastable strings


I wish to collapse the output of spdep::moran.test into a single string that is regularly structured with variable names and values and that can both be saved as a text value into a dataframe, and be human readable in the RStudio console and copy-pastable into MS Word to form a table without too many additional manual adjustments. (I have multiple tests to run and wish to copy-paste their output in one go.)

In the course of looking for a solution, I stumbled upon the report package which claims to turn an htest class object into a "report" (I don't know what this looks like in R) and thus may address my goal to some extent. However, the report function doesn't work on moran.test, as presented in the code below.

I am exploring and there are probably alternative and more straightforward approaches which I haven't considered. Thus my question is twofold: 1. Solve the immediate issue with report and/or 2. Provide an alternative and more efficient solution to my goal.

The data preparation below is drawn from https://mgimond.github.io/simple_moransI_example.

library(sf)
library(spdep)
library(report)

# Load shapefile
s <- readRDS(url("https://github.com/mgimond/Data/raw/gh-pages/Exercises/nhme.rds"))

# Prevent error "old-style crs object detected; please recreate object with a recent sf::st_crs()"
st_crs(s) <- st_crs(s)

# Define neighboring polygons
nb <- poly2nb(s, queen=TRUE)

# Assign weights to the neighbors
lw <- nb2listw(nb, style="W", zero.policy=TRUE)

# Run Moran’s I test
(mt <- moran.test(s$Income,lw, alternative="greater"))
#Moran I test under randomisation
#data:  s$Income  
#weights: lw    
#Moran I statistic standard deviate = 5.8525, p-value = 2.421e-09
#alternative hypothesis: greater
#sample estimates:
#  Moran I statistic       Expectation          Variance 
#0.68279551       -0.04000000        0.01525284

# Moran’s I test is of class htest required by function report::report
class(mt)
#[1] "htest"

# Function report::report returns an error
report(mt)
#Error in `$<-.data.frame`(`*tmp*`, "tau", value = c(`Moran I statistic` = 0.68279551202875,  : 
#  replacement has 3 rows, data has 1

The desired output could look something like:

"P-value 2.421e-09 | Statistic 0.68279551 | Expectation -0.04000000 | Variance 0.01525284"

The point is the names and values, not the separators. This is based on my current assumptions of how to approach this task, which are probably imperfect.


Solution

  • You might want to take a look at the broom package:

    broom::tidy(mt)
    #> # A tibble: 1 x 7
    #>   estimate1 estimate2 estimate3 statistic    p.value method          alternative
    #>       <dbl>     <dbl>     <dbl>     <dbl>      <dbl> <chr>           <chr>      
    #> 1     0.683     -0.04    0.0153      5.85    2.42e-9 Moran I test u… greater
    
    library(tidyverse)
    mt %>%
      broom::tidy() %>%
      as.list() %>% 
      enframe() %>%
      mutate(value = value %>% as.character()) %>% unite(data, sep = "=") %>%
      pull(data) %>%
      paste0(collapse = ", ")
    #> [1] "estimate1=0.68279551202875, estimate2=-0.04, estimate3=0.0152528397222445, statistic=c(`Moran I statistic standard deviate` = 5.85248209823413), p.value=2.42145194022024e-09, method=Moran I test under randomisation, alternative=greater"
    

    You can make a table and create a csv file from multiple tests (e.g. having multiple objects of class htest like mt, mt1 and mt2):

    list(mt, mt2, mt3) %>% map(broom::tidy) %>% bind_rows() %>% write_csv("tests.csv")