14

I've been doing some background reading about cartograms recently and stumbled upon interesting alternative - value-by-alpha maps.

Concept is described in more details here and full paper is available [not openly tho] [here]2.

There are some details about the implementation on indiemaps blog:

... all of the above graphics were produced with ActionScript 3, using just a text editor and the latest free Flex SDK...

How could you implement something like that in GIS package (ArcGIS? QuantumGIS?)? Or R and ggplot2? Or Python?

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
radek
  • 10,579
  • 12
  • 86
  • 121

7 Answers7

7

Here is a method for doing Alpha By Value in QGIS

http://nathanw.net/2013/06/27/alpha-by-value-choropleth/

You can use the new ramp_color and scale_linear functions and data defined symbols

regexp_replace( ramp_color('usa', scale_linear( "unemployed_by_county_xgv_Rate",0,15,0,1)),',[^,]*$',','|| toint(scale_linear("unemployed_by_county_xgv_Labor_Force",0,100000,0,255)))

enter image description here

Nathan W
  • 34,706
  • 5
  • 97
  • 148
  • 1
    Nice work (although I'm not sure about the color ramp - although I realize it is just a useful how-to). A nice addition might be how to make the legend to go with it. – Andy W Jun 28 '13 at 12:34
  • Yeah the colour ramp didn't really work. If you have a better suggestion I can make a updated image. Have been thinking about the legend, will update once I have a good plan. (That will work with QGIS 2.0) – Nathan W Jun 28 '13 at 13:48
  • 1
    I did try white and black which has a pretty cool look http://i.imgur.com/Wfg8T8P.png – Nathan W Jun 28 '13 at 13:59
  • Check out the original Roth article - they have suggested ramps. Because of the desaturation, they use some of the more (initially) saturated bivariate color brewer ramps. Black backgrounds look nice for these because they provide greater/more stunning contrast with the background IMO. I've written some about my speculation here. – Andy W Jun 28 '13 at 16:13
  • @AndyW updated with a (maybe) better image. – Nathan W Jun 29 '13 at 09:43
  • @AndyW link to the 'original Roth article' seems to be dead :/ – radek Sep 10 '14 at 19:48
  • value by alpha (as discirbed by https://nathanw.net/2013/06/27/alpha-by-value-choropleth-in-qgis/) works pretty fine with qgis 2.1n (where m > 12, i guess). especially if you use virtual fields for the calculations Nathan Woodrow describes - but: in his first step, he is creating a continuously colored coropleth map based on the scale_linear command. has anybody any idea how to produce a value-by-alpha map in a similar way with a color setting that is based on a classified color set (e.g. based on natural breaks or quantiles)? i.e. how can i return rgb-values into a field that are based on an – robert tuw Aug 11 '16 at 16:42
5

In R you can read in the polygons and plot them on a device that supports transparency. Here I'm using the windows() device, R 2.12.0 with rgdal and sp packages.

## read some example polygons
library(rgdal)
dsn <- system.file("vectors/ps_cant_31.MIF", package = "rgdal")[1]
ps_cant_31 <- readOGR(dsn=dsn, layer="ps_cant_31")

## scale population values 

ps_cant_31$sclpop <- sqrt((ps_cant_31$POP - min(ps_cant_31$POP))/ diff(range(ps_cant_31$POP)))

## randomly assign 0 or 1
ps_cant_31$rand <- sample(0:1, length(ps_cant_31$POP), replace = TRUE)

## plot red or blue, scaled by population
plot(ps_cant_31,  col = ifelse(ps_cant_31$rand == 0, rgb(0, 0, 1, ps_cant_31$sclpop), rgb(1, 0, 0, ps_cant_31$sclpop)))

alt text

mdsumner
  • 8,196
  • 1
  • 27
  • 30
  • Thanks mdsumner! That looks closest to what I'd like to achieve. Started messing with spatial functionality of R a little so will try to replicate it with my data now. – radek Nov 24 '10 at 12:54
  • Some more examples in R: https://dsparks.wordpress.com/2011/10/24/isarithmic-maps-of-public-opinion-data/ – radek Oct 24 '11 at 13:43
4

I'd suggest you check out the Geo Vista site and their software. The Visual Inquiry Toolkit, provides a GUI program to implement the bi-variate chloropleth maps (I know one poster on here works at that project and may be able to point to other resources).

I think the cartogrammer blog post is sufficient to explain the technique, but here is a pretty cool article (open to the public) to see its use in practice.

Geovisual analytics to enhance spatial scan statistic interpretation: an analysis of U.S. cervical cancer mortality Jin Chen , Robert E Roth , Adam T Naito , Eugene J Lengerich and Alan M MacEachren International Journal of Health Geographics 2008, 7:57

I hope to see some code examples for Python and R too! Basically any program that can implement a two-scale color scheme (or bivariate) can create a value by alpha map. Although all of the implementations I have seen listed so far are for choropleth maps, there is no reason you couldn't implement this for a raster or point based map as well.


I've recently written a blog post about how to implement them in ArcGIS, Making value by alpha maps with ArcMap. It basically entails making separate layers for a given transparency, and then utilizing the vector editing tools available within ArcMap to produce the necessary bivariate legend (or using a fake inset map to replicate the legend if you want to produce a black background VBA map).

enter image description here

enter image description here

Andy W
  • 4,234
  • 5
  • 45
  • 69
3

You could do this is uDig using an SLD based style that calculates the % opacity using the math functions in the OGC filter spec. I'm not sure how efficient it would be but could certainly be used for proof of concept.

I've built a demo at http://ian01.geog.psu.edu/geoserver/www/cartogram/alphabyvalue.html with a discussion at http://ian01.geog.psu.edu/geoserver_docs/cartogram/cartogram.html. Turns out it is pretty easy.

          <PolygonSymbolizer>
            <Fill>
              <!-- CssParameters allowed are fill (the color) and fill-opacity -->
              <CssParameter name="fill">#4DFF4D</CssParameter>
              <CssParameter name="fill-opacity">
                <ogc:Div>
                  <ogc:PropertyName>PERSONS</ogc:PropertyName>
                  <ogc:Literal>30e6</ogc:Literal>
                </ogc:Div>
              </CssParameter>
            </Fill>     
          </PolygonSymbolizer>

(where 30e6 is the population of California)

Ian Turton
  • 81,417
  • 6
  • 84
  • 185
  • Thanks Iant. Would it be possible to automate it and apply these styles on 'per polygon' basis using one of the variables? – radek Oct 24 '10 at 13:30
  • You would need to put a function to calculate a value between 0-1 in the opacity parameter. – Ian Turton Oct 24 '10 at 14:20
  • Shouldn't it be "Value-by-alpha Map" instead of "Value-by-alpha Cartograms"? http://ian01.geog.psu.edu/geoserver_docs/cartogram/index.html states correctly that: "A cartogram is a map where some other variable is substituted in place of area or distance." – underdark Nov 14 '10 at 11:47
  • 1
    probably :-) But the other definition of cartogram is "a map that you messed about with to make a point" – Ian Turton Nov 14 '10 at 16:01
2

You could use GDAL to do this, either through VRT files, or by setting the values programmatically, by accessing the fourth band of an RGBA dataset (such as a GeoTiff). I'll show how using a VRT because its somewhat simpler: starting with an RGB Tiff, you could create a palleted image as per the FAQ:

# translate the rgba tiff to a VRT
gdal_translate -of VRT rgb.tif rgb.vrt

# modify the color table in an editor

# translate back to an image
gdal_translate rgb.vrt mask-by-alpha.tif

In the editing step, open the resulting rgb.vrt, and modify the color table as needed, adjusting the c4 values (0-255) to set alpha:

<VRTDataset rasterXSize="226" rasterYSize="271">
  <VRTRasterBand dataType="Byte" band="1">
    <ColorInterp>Palette</ColorInterp>
    <ColorTable>
      <Entry c1="238" c2="238" c3="238" c4="0"/>
      <Entry c1="237" c2="237" c3="237" c4="64"/>
      <Entry c1="236" c2="236" c3="236" c4="128"/>
      <Entry c1="229" c2="229" c3="229" c4="255"/>
    </ColorTable>
  </VRTRasterBand>
</VRTDataset> 
scw
  • 16,391
  • 6
  • 64
  • 101
  • Thanks scw. What exactly would my workflow look like for scenario with 3k vector polygons as an input? Should I first create choropleth map without alpha - save as raster - and then adjust raster values? The values would have to be adapted on 'per polygon' basis I presume? And I'd have to automate it somehow according to the field that will drive alpha values.. – radek Oct 22 '10 at 19:00
1

One more description from Josh on how to implement it in QGIS

enter image description here

Very good and detailed tutorial.

radek
  • 10,579
  • 12
  • 86
  • 121
1

I like that - I'd never really thought of that concept before.

If you have access to FME or the Data Interoperability extension in ArcGIS, then there are a bunch of transformers that will let you manipulate band values in a raster dataset, including alpha band.

RasterExpressionEvaluator, RasterInterpretationCoercer and RasterBandOrderer are the ones I'd try at first. Then you could import/use the data in any GIS/Visulisation tool.

A colleague of mine used a similar idea to create passwords 'hidden' inside a raster image: http://www.fmepedia.com/index.php/PasswordGenerator

Disclosure: I do work for Safe Software - makers of FME.

Mark Ireland
  • 13,147
  • 3
  • 33
  • 67
  • Thx Mark. Unfortunately I don't have an access to FME. And Data Interoperability is not included in my uni license for ArcGIS :[ – radek Oct 22 '10 at 19:03