Quanto tempo dovrei aspettare PostGIS per geocodificare indirizzi ben formattati?


17

Quanto tempo dovrei aspettare PostGIS per geocodificare indirizzi ben formattati?

Ho installato PostgreSQL 9.3.7 e PostGIS 2.1.7, caricato i dati della nazione e tutti i dati degli stati ma ho trovato che la geocodifica è molto più lenta di quanto mi aspettassi. Ho impostato le mie aspettative troppo alte? Ricevo in media 3 singoli geocodici al secondo. Devo fare circa 5 milioni e non voglio aspettare tre settimane per questo.

Questa è una macchina virtuale per l'elaborazione di matrici R giganti e ho installato questo database sul lato in modo che la configurazione possa sembrare un po 'sciocca. Se una modifica importante nella configurazione della VM sarà di aiuto, posso modificare la configurazione.

Specifiche hardware

Memoria: processori da 65 GB: 6 lscpumi dà questo:

# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                6
On-line CPU(s) list:   0-5
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             6
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 58
Stepping:              0
CPU MHz:               2400.000
BogoMIPS:              4800.00
Hypervisor vendor:     VMware
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              30720K
NUMA node0 CPU(s):     0-5

Il sistema operativo è centos, uname -rvdà questo:

# uname -rv
2.6.32-504.16.2.el6.x86_64 #1 SMP Wed Apr 22 06:48:29 UTC 2015

Postgresql config

> select version()
"PostgreSQL 9.3.7 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11), 64-bit"
> select PostGIS_Full_version()
POSTGIS="2.1.7 r13414" GEOS="3.4.2-CAPI-1.8.2 r3921" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.2, released 2012/10/08" LIBXML="2.7.6" LIBJSON="UNKNOWN" TOPOLOGY RASTER"

Sulla base dei precedenti suggerimenti a questi tipi di query, ho aumentato shared_buffersil postgresql.conffile a circa 1/4 della RAM disponibile e le dimensioni effettive della cache a 1/2 della RAM:

shared_buffers = 16096MB     
effective_cache_size = 31765MB

Ho installed_missing_indexes()e (dopo aver risolto inserti duplicati in alcune tabelle) non ho riscontrato errori.

Esempio di geocodifica SQL n. 1 (batch) ~ tempo medio di 2,8 / sec

Sto seguendo l'esempio di http://postgis.net/docs/Geocode.html , che mi ha fatto creare una tabella contenente l'indirizzo al geocode e quindi fare un SQL UPDATE:

UPDATE addresses_to_geocode
              SET  (rating, longitude, latitude,geo) 
              = ( COALESCE((g.geom).rating,-1),
              ST_X((g.geom).geomout)::numeric(8,5), 
              ST_Y((g.geom).geomout)::numeric(8,5),
              geo )
              FROM (SELECT "PatientId" as PatientId
              FROM addresses_to_geocode 
              WHERE "rating" IS NULL ORDER BY PatientId LIMIT 1000) As a
              LEFT JOIN (SELECT "PatientId" as PatientId, (geocode("Address",1)) As geom
              FROM addresses_to_geocode As ag
              WHERE ag.rating IS NULL ORDER BY PatientId LIMIT 1000) As g ON a.PatientId = g.PatientId
              WHERE a.PatientId = addresses_to_geocode."PatientId";

Sto usando una dimensione batch di 1000 sopra e ritorna in 337.70 secondi. È un po 'più lento per i lotti più piccoli.

Esempio di geocodifica SQL n. 2 (riga per riga) ~ il tempo medio è 1,2 / sec

Quando scavo nei miei indirizzi eseguendo i geocodici uno alla volta con un'affermazione simile a questa (tra l'altro, l'esempio seguente ha richiesto 4,14 secondi),

SELECT g.rating, ST_X(g.geomout) As lon, ST_Y(g.geomout) As lat, 
    (addy).address As stno, (addy).streetname As street, 
    (addy).streettypeabbrev As styp, (addy).location As city, 
    (addy).stateabbrev As st,(addy).zip 
FROM geocode('6433 DROMOLAND Cir NW, MASSILLON, OH 44646',1) As g;

è un po 'più lento (2,5 volte per record) ma posso vedere la distribuzione dei tempi delle query e vedere che è una minoranza di lunghe query che sta rallentando di più (solo i primi 2600 su 5 milioni hanno tempi di ricerca). Cioè, il 10% superiore sta prendendo una media di circa 100 ms, il 10% inferiore in media 3,69 secondi, mentre la media è 754 ms e la mediana è 340 ms.

# Just some interaction with the data in R
> range(lookupTimes[1:2600])
[1]  0.00 11.54
> median(lookupTimes[1:2600])
[1] 0.34
> mean(lookupTimes[1:2600])
[1] 0.7541808
> mean(sort(lookupTimes[1:2600])[1:260])
[1] 0.09984615
> mean(sort(lookupTimes[1:2600],decreasing=TRUE)[1:260])
[1] 3.691269
> hist(lookupTimes[1:2600]

Tempi di geocodifica per le prime 2600 righe

Altri pensieri

Se non riesco a ottenere un ordine di grandezza in aumento delle prestazioni, ho pensato che avrei potuto almeno fare un'ipotesi plausibile sulla previsione di tempi di geocodifica lenti, ma non è ovvio per me perché gli indirizzi più lenti sembrano richiedere molto più tempo. Sto eseguendo l'indirizzo originale attraverso un passaggio di normalizzazione personalizzato per assicurarmi che sia formattato correttamente prima che la geocode()funzione lo ottenga:

sql=paste0("select pprint_addy(normalize_address('",myAddress,"'))")

dove myAddressè una [Address], [City], [ST] [Zip]stringa compilata da una tabella degli indirizzi utente da un database non postgresql.

Ho provato (non riuscito) a installare l' pagc_normalize_addressestensione, ma non è chiaro che questo porterà il tipo di miglioramento che sto cercando. Modificato per aggiungere informazioni di monitoraggio come da suggerimento

Prestazione

È collegata una CPU: [modifica, solo un processore per query, quindi ho 5 CPU inutilizzate]

top - 14:10:26 up 1 day,  3:11,  4 users,  load average: 1.02, 1.01, 0.93
Tasks: 219 total,   2 running, 217 sleeping,   0 stopped,   0 zombie
Cpu(s): 15.4%us,  1.5%sy,  0.0%ni, 83.1%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65056588k total, 64613476k used,   443112k free,    97096k buffers
Swap: 262139900k total,    77164k used, 262062736k free, 62745284k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 3130 postgres  20   0 16.3g 8.8g 8.7g R 99.7 14.2 170:14.06 postmaster
11139 aolsson   20   0 15140 1316  932 R  0.3  0.0   0:07.78 top
11675 aolsson   20   0  135m 1836 1504 S  0.3  0.0   0:00.01 wget
    1 root      20   0 19364 1064  884 S  0.0  0.0   0:01.84 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.06 kthreadd

Esempio di attività del disco sulla partizione dati mentre un proc è ancorato al 100%: [modifica: solo un processore utilizzato da questa query]

# dstat -tdD dm-3 1
----system---- --dsk/dm-3-
  date/time   | read  writ
12-06 14:06:36|1818k 3632k
12-06 14:06:37|   0     0
12-06 14:06:38|   0     0
12-06 14:06:39|   0     0
12-06 14:06:40|   0    40k
12-06 14:06:41|   0     0
12-06 14:06:42|   0     0
12-06 14:06:43|   0  8192B
12-06 14:06:44|   0  8192B
12-06 14:06:45| 120k   60k
12-06 14:06:46|   0     0
12-06 14:06:47|   0     0
12-06 14:06:48|   0     0
12-06 14:06:49|   0     0
12-06 14:06:50|   0    28k
12-06 14:06:51|   0    96k
12-06 14:06:52|   0     0
12-06 14:06:53|   0     0
12-06 14:06:54|   0     0 ^C

Analizza quel SQL

Questo proviene EXPLAIN ANALYZEda quella query:

"Update on addresses_to_geocode  (cost=1.30..8390.04 rows=1000 width=272) (actual time=363608.219..363608.219 rows=0 loops=1)"
"  ->  Merge Left Join  (cost=1.30..8390.04 rows=1000 width=272) (actual time=110.934..324648.385 rows=1000 loops=1)"
"        Merge Cond: (a.patientid = g.patientid)"
"        ->  Nested Loop  (cost=0.86..8336.82 rows=1000 width=184) (actual time=10.676..34.241 rows=1000 loops=1)"
"              ->  Subquery Scan on a  (cost=0.43..54.32 rows=1000 width=32) (actual time=10.664..18.779 rows=1000 loops=1)"
"                    ->  Limit  (cost=0.43..44.32 rows=1000 width=4) (actual time=10.658..17.478 rows=1000 loops=1)"
"                          ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode addresses_to_geocode_1  (cost=0.43..195279.22 rows=4449758 width=4) (actual time=10.657..17.021 rows=1000 loops=1)"
"                                Filter: (rating IS NULL)"
"                                Rows Removed by Filter: 24110"
"              ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode  (cost=0.43..8.27 rows=1 width=152) (actual time=0.010..0.013 rows=1 loops=1000)"
"                    Index Cond: ("PatientId" = a.patientid)"
"        ->  Materialize  (cost=0.43..18.22 rows=1000 width=96) (actual time=100.233..324594.558 rows=943 loops=1)"
"              ->  Subquery Scan on g  (cost=0.43..15.72 rows=1000 width=96) (actual time=100.230..324593.435 rows=943 loops=1)"
"                    ->  Limit  (cost=0.43..5.72 rows=1000 width=42) (actual time=100.225..324591.603 rows=943 loops=1)"
"                          ->  Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode ag  (cost=0.43..23534259.93 rows=4449758000 width=42) (actual time=100.225..324591.146 rows=943 loops=1)"
"                                Filter: (rating IS NULL)"
"                                Rows Removed by Filter: 24110"
"Total runtime: 363608.316 ms"

Scopri una migliore ripartizione su http://explain.depesz.com/s/vogS


1
Cosa fa la macchina quando si eseguono le query? Si blocca su IO o il collo di bottiglia è altrove?
fino al

1
Quanti stati hai caricato. In genere ottengo ovunque da 30 ms - 150 ms per indirizzo su una scatola di Windows a 64 bit con ram da 4-8 GB. Di solito però sto lavorando solo con 1 o 2 stati. Non ho fatto benchmark sull'impatto di più stati sulle prestazioni.
LR1234567,

@ LR1234567 50 stati
aaryno,

1
La CPU @til_b è fissata al 99,7%
aaryno il

Sembra che aspetteremo solo un paio di settimane per finire questa cosa dal momento che è una cosa sola e che ci rimarrà un sacco di succo una volta fatto per stare al passo con il carico di runtime di 100 indirizzi / giorno Stiamo facendo esperienza. Lo terrò aperto fino a quando non avremo finito nel caso in cui dovesse emergere qualcosa di davvero interessante che ci permetta di aggirare le nostre CPU fisse.
aaryno,

Risposte:


7

Ho passato molto tempo a sperimentare questo, penso che sia meglio pubblicare separatamente poiché sono di diversa angolazione.

Questo è davvero un argomento complesso, vedi maggiori dettagli nel mio post sul blog sulla configurazione del server di geocodifica e sullo script che ho usato . Ecco alcuni brevi riassunti:

Un server con solo 2 stati dati è sempre più veloce di un server caricato con tutti i dati 50 stati.

Ho verificato questo con il mio PC di casa in tempi diversi e due diversi server Amazon AWS.

Il mio server di livello gratuito AWS con dati a 2 stati ha solo 1G RAM, ma ha prestazioni costanti 43 ~ 59 ms per i dati con 1000 record e 45.000 record.

Ho usato esattamente la stessa procedura di configurazione per un server AWS 8G RAM con tutti gli stati caricati, esattamente lo stesso script e dati, e le prestazioni sono scese a 80 ~ 105 ms.

La mia teoria è che quando il geocoder non può corrispondere esattamente all'indirizzo, ha iniziato ad ampliare il raggio di ricerca e ignorare alcune parti, come il codice postale o la città. Ecco perché i documenti geocodici si vantano di poter ricolonizzare l'indirizzo con un codice postale errato, anche se ci sono voluti 3000 ms.

Con solo 2 stati dati caricati, il server impiegherà molto meno tempo nella ricerca infruttuosa o in una partita con punteggio molto basso, perché può cercare solo in 2 stati.

Ho provato a limitare questo impostando il restrict_regionparametro sui multipoligoni di stato nella funzione geocodice, sperando che ciò evitasse la ricerca infruttuosa poiché sono quasi sicuro che la maggior parte degli indirizzi abbia lo stato corretto. Confronta queste due versioni:

  select geocode('501 Fairmount DR , Annapolis, MD 20137',1); 
  select geocode('501 Fairmount DR , Annapolis, MD 20137', 1, the_geom) from tiger.state where statefp = '24';

L'unica differenza fatta dalla seconda versione è che normalmente se eseguo di nuovo immediatamente la stessa query sarà molto più veloce perché i dati correlati sono stati memorizzati nella cache, ma la seconda versione ha disabilitato questo effetto.

Quindi restrict_regionnon funziona come desideravo, forse è stato usato solo per filtrare il risultato di più colpi, non per limitare gli intervalli di ricerca.

Puoi sintonizzare un po 'il tuo postgre conf.

Il solito sospettato di installare gli indici mancanti, il vuoto di analisi non ha fatto alcuna differenza per me, perché lo script di download ha già fatto la manutenzione necessaria, a meno che tu non abbia sbagliato.

Tuttavia, l'impostazione di Postgre Conf secondo questo post ha aiutato. Il mio server in scala reale con 50 stati aveva 320 ms con configurazione predefinita per alcuni dati peggiori, è migliorato a 185 ms con 2G shared_buffer, 5G cache e è andato a 100 ms ulteriormente con la maggior parte delle impostazioni ottimizzate in base a quel post.

Questo è più rilevante per i postgis e le loro impostazioni sembrano essere simili.

La dimensione del batch di ogni commit non contava molto per il mio caso. La documentazione relativa al geocodice utilizzava una dimensione di lotto 3. Ho sperimentato valori compresi tra 1, 3, 5 e 10. Non ho riscontrato alcuna differenza significativa con questo. Con lotti di dimensioni inferiori si effettuano più commit e aggiornamenti, ma penso che il vero collo di bottiglia non sia qui. In realtà sto usando la dimensione batch 1 ora. Poiché ci sono sempre degli indirizzi inattesi che non sono stati generati, si verificherà un'eccezione, imposterò l'intero batch con errori come ignorato e procederò per le righe rimanenti. Con la dimensione batch 1 non ho bisogno di elaborare la tabella la seconda volta per geocodificare i possibili buoni record nel batch contrassegnato come ignorato.

Naturalmente questo dipende da come funziona lo script batch. Pubblicherò la mia sceneggiatura con maggiori dettagli in seguito.

Puoi provare a utilizzare l'indirizzo normalizza per filtrare l'indirizzo errato se adatto al tuo utilizzo. Ho visto qualcuno menzionarlo da qualche parte, ma non ero sicuro di come funzioni poiché la funzione di normalizzazione funziona solo in formato, non posso davvero dirti quale indirizzo non è valido.

Più tardi mi sono reso conto che se l'indirizzo è ovviamente in cattive condizioni e vuoi saltarli, questo potrebbe aiutare. Ad esempio, ho molti indirizzi mancanti del nome della strada o addirittura dei nomi delle strade. La normalizzazione prima di tutto dell'indirizzo sarà relativamente veloce, quindi puoi filtrare l'evidente indirizzo errato per te, quindi saltarlo. Tuttavia, ciò non ha comportato il mio utilizzo poiché un indirizzo senza numero civico o addirittura nome della strada potrebbe ancora essere mappato sulla strada o sulla città e tali informazioni sono ancora utili per me.

E la maggior parte degli indirizzi che non possono essere geocodificati nel mio caso in realtà hanno tutti i campi, solo che non c'è corrispondenza nel database. Non puoi filtrare questi indirizzi semplicemente normalizzandoli.

MODIFICA Per maggiori dettagli, vedi il mio post sul blog sulla configurazione del server di geocodifica e lo script che ho usato .

EDIT 2 Ho terminato la geocodifica di 2 milioni di indirizzi e ho ripulito molto gli indirizzi in base al risultato della geocodifica. Con input puliti meglio, il processo batch successivo viene eseguito molto più velocemente. Con chiaro intendo che alcuni indirizzi sono ovviamente sbagliati e dovrebbero essere rimossi, o avere contenuti imprevisti per il geocoder può causare problemi sulla geocodifica. La mia teoria è: la rimozione di indirizzi errati può evitare di incasinare la cache, migliorando significativamente le prestazioni su indirizzi validi.

Ho separato l'input in base allo stato per assicurarmi che ogni lavoro potesse avere tutti i dati necessari per il geocoding memorizzati nella RAM. Tuttavia, ogni indirizzo errato nel lavoro fa sì che il geocoder cerchi in più stati, il che potrebbe rovinare la cache.


Ottima risposta Sulla mia scatola, come succede, il filtraggio per stato accelera la partita di circa un fattore di 50 (!) Ma sospetto che potrei avere problemi di indice.
ako,

2
  1. Secondo questo thread di discussione , dovresti utilizzare la stessa procedura di normalizzazione per elaborare i dati Tiger e il tuo indirizzo di input. Poiché i dati Tiger sono stati elaborati con il normalizzatore incorporato, è meglio utilizzare solo il normalizzatore incorporato. Anche se hai fatto funzionare pagc_normalizer, potrebbe non aiutarti se non lo usi per aggiornare i dati di Tiger.

    Detto questo, penso che geocode () chiamerà normalizer comunque, quindi normalizzare l'indirizzo prima che il geocoding possa non essere davvero utile. Un possibile utilizzo del normalizzatore potrebbe essere il confronto tra l'indirizzo normalizzato e l'indirizzo restituito da geocode (). Con entrambi normalizzati, potrebbe essere più facile trovare il risultato di geocodifica sbagliato.

    Se riesci a filtrare un indirizzo errato dal geocodice tramite il normalizzatore, ciò sarà di grande aiuto. Tuttavia, non vedo che il normalizzatore abbia qualcosa come un punteggio o una valutazione della partita.

  2. Lo stesso thread di discussione ha anche menzionato un passaggio di debug geocode_addressper mostrare ulteriori informazioni. Il nodo geocode_addressnecessita di un input di indirizzo normalizzato.

  3. Il geocoder è veloce per la corrispondenza esatta, ma richiede molto più tempo per i casi difficili. Ho scoperto che esiste un parametro restrict_regione ho pensato che forse limiterebbe la ricerca infruttuosa se imposto il limite come stato poiché sono abbastanza sicuro in quale stato si troverà. Si è scoperto che impostandolo su uno stato sbagliato non si è fermato il geocode l'indirizzo corretto, anche se richiede del tempo.

    Quindi forse il geocoder cercherà in tutti i posti possibili se la prima ricerca esatta non ha corrispondenza. Ciò lo rende in grado di elaborare l'input con alcuni errori, ma rende anche la ricerca molto lenta.

    Penso che sia buono per un servizio interattivo accettare input con errori, ma a volte potremmo voler rinunciare a un piccolo set di indirizzi errati per avere prestazioni migliori nella geocodifica batch.


Qual è stato l'impatto restrict_regionsui tempi quando hai impostato lo stato corretto? Inoltre, dal thread postgis-utenti che hai collegato sopra, menzionano in particolare problemi con indirizzi come quelli 1020 Highway 20che ho incontrato.
aaryno,

L'impostazione dello stato corretto probabilmente non migliorerà, poiché se l'indirizzo è ben formattato il geocoder può comunque ottenere lo stato corretto.
dracodoc,

1

Pubblicherò questa risposta, ma spero che un altro collaboratore contribuirà a scomporre quanto segue, che penso dipingerà un quadro più coerente:

Qual è l'impatto del numero di stati caricati sulla geocodifica? Ho tutti e 50 e vedo prestazioni molto inferiori rispetto a @ LR1234567 (ovvero 8 volte il tempo per geocode).

Qual è il metodo più efficiente per la geocodifica di massa? Sto eseguendo un processo seriale, eseguendo ripetutamente batch di 100 fino a quando l'intero backload è terminato. Sarebbe preferibile un approccio multi-thread, ma quali sono gli approcci consigliati?

Qual è l'impatto della virtualizzazione sulla geocodifica PostgreSQL? Sto indovinando il 10% sulla base di alcuni altri post, ma ho poca fiducia in quella risposta

Ora la mia risposta, che è solo un aneddoto:

Il migliore che sto ottenendo (basato su una singola connessione) è una media di 208 ms per geocode. Questo viene misurato selezionando gli indirizzi in modo casuale dal mio set di dati, che si estende negli Stati Uniti. Include alcuni dati sporchi, ma i messaggi più lunghi geocodenon sembrano essere cattivi in modi ovvi.

L'essenza di ciò è che sembro essere associato alla CPU e che una singola query è associata a un singolo processore. Posso parallelizzare ciò avendo in teoria connessioni multiple che si UPDATEverificano su segmenti complementari della addresses_to_geocodetabella. Nel frattempo, sto prendendo geocodeuna media di 208 ms su set di dati a livello nazionale. La distribuzione è distorta sia per quanto riguarda la maggior parte dei miei indirizzi sia per quanto tempo impiegano (ad es. Vedere l'istogramma sopra) e la tabella sotto.

Il mio approccio migliore finora è farlo in lotti di 10000, con alcuni miglioramenti stimabili dal fare di più per lotto. Per lotti di 100 stavo ottenendo circa 251ms, con 10000 sto ottenendo 208ms.

UPDATE addresses_to_geocode 
SET (rating, longitude, latitude, geo) = 
   (COALESCE((g.geom).rating,-1), 
            ST_X((g.geom).geomout)::numeric(8,5),   
            ST_Y((g.geom).geomout)::numeric(8,5), 
            geo) 
   FROM (
       SELECT "PatientId" as PatientId 
       FROM addresses_to_geocode  
       WHERE "rating" IS NULL 
       ORDER BY PatientId LIMIT 100) As a 
   LEFT JOIN (
       SELECT "PatientId" as PatientId, (geocode("Address",1)) As geom 
       FROM addresses_to_geocode As ag 
       WHERE ag.rating IS NULL 
       ORDER BY PatientId LIMIT 100) As g 
   ON a.PatientId = g.PatientId 
   WHERE a.PatientId = addresses_to_geocode."PatientId";

Devo citare i nomi dei campi a causa di come RPostgreSQL crea le tabelle dbWriteTable

Sono circa 4 volte più veloci che se li facessi un disco alla volta. Quando li faccio uno alla volta posso ottenere una suddivisione per stato (vedi sotto). Ho fatto questo per controllare e vedere se uno o più stati TIGER avevano un carico o un indice difettoso, che mi aspettavo di causare scarse geocodeprestazioni in senso statale. Ovviamente ho dei dati errati (alcuni indirizzi sono persino indirizzi e-mail!), Ma la maggior parte di essi è ben formattata. Come ho detto prima, alcune delle query più lunghe non presentano evidenti carenze nel loro formato. Di seguito è riportata una tabella con il numero, il tempo minimo di interrogazione, il tempo medio di interrogazione e il tempo di interrogazione massimo per stati da 3000-alcuni indirizzi casuali dal mio set di dati:

       state   n  min      mean   max
1          .   1 0.00 0.0000000  0.00
12        DC   6 0.07 0.0900000  0.10
9  CHIHUAHUA   1 0.16 0.1600000  0.16
2         00   1 0.18 0.1800000  0.18
6         AR   1 0.37 0.3700000  0.37
27        MT  17 0.14 0.4229412  1.01
14        GA  37 0.22 0.4340541  2.78
10        CO   1 0.54 0.5400000  0.54
16        IL 390 0.16 0.5448974  3.75
8         CA 251 0.17 0.5546614  3.58
5         AL   4 0.13 0.5575000  0.86
18        KS   3 0.43 0.5966667  0.75
23        ME 121 0.14 0.6266116  7.88
35        SC 390 0.14 0.6516923  6.88
24        MI  62 0.12 0.6524194  3.36
40        WA   3 0.23 0.7500000  1.41
32        OK 145 0.17 0.7538621  5.84
20        LA   1 0.76 0.7600000  0.76
31        OH 551 0.00 0.7623775 10.27
17        IN 108 0.19 0.7864815  3.64
43      <NA>  89 0.00 0.8152809  4.98
15        IA   1 0.82 0.8200000  0.82
30        NY 227 0.19 0.8227753 28.47
19        KY   3 0.56 0.8333333  1.36
36        TN 333 0.11 0.8566667  6.45
28        NC 129 0.24 0.8843411  4.07
13        FL  70 0.28 0.9131429  4.65
7         AZ 101 0.20 0.9498020  6.33
34        PA  56 0.14 0.9594643  3.61
29        NJ   1 1.03 1.0300000  1.03
33        OR 101 0.24 1.0966337 14.89
26        MS  28 0.25 1.1503571 11.89
3          9   6 0.58 1.2133333  1.93
4         AK   1 1.25 1.2500000  1.25
22        MD   9 0.50 1.3055556  4.17
25        MO  22 0.31 1.3381818  4.20
42        WY   1 1.38 1.3800000  1.38
38        VA 127 0.20 1.3873228  5.69
37        TX   4 0.53 1.4800000  3.28
21        MA   4 0.47 1.5725000  3.63
11        CT   5 0.38 1.6760000  4.68
39        VT   1 2.25 2.2500000  2.25
41        WI   2 2.27 2.2850000  2.30
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.