Filtering out states from a geojson?

166 views
Skip to first unread message

Justin Brumley

unread,
Jun 12, 2014, 9:44:34 AM6/12/14
to dc-js-us...@googlegroups.com
Does anybody know of a good way to filter out only a certain state from a list of all the counties in the U.S.? I'm using a file I got from here. I know that I am looking for a certain ID but I do not know how or where to check for that ID to limit the render to only one state. I really do not want to have to go through the 6000 line file removing all the entries I don't need.

Adam Reynolds

unread,
Jun 12, 2014, 10:02:54 AM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com
Create a dimension using states, create a group, then create a 'fake' group that excludes that state. Pass the fake group into the chart.

Something I knocked up earlier where I wanted to exclude staff with no names:
db.dimensions["staffDimension"] = db.crossStore["tasks"].dimension(function (d) {return d.starting_staff_name;});
var staffGroup = db.dimensions["staffDimension"].group();

var excludedNoNameStaffGroup = {
all:function () {
var g = [];
staffGroup.all().forEach(function(d,i){
if (d.key != '') {g.push(d);}
});
return g;
},
top:function (k) {
var g = [];
staffGroup.top(k).forEach(function(d,i){
if (d.key != '') {g.push(d);}
});
return g;
}
};

var staffRowChart = dc.rowChart("#tasks-chart2");
        staffRowChart
.width(db.constants["chartWidth"])
.height(db.constants["chartHeight"])
.margins({top: 20, left: 10, right: 10, bottom: 30})
.dimension(db.dimensions["staffDimension"])
.group(excludedNoNameStaffGroup)
.cap(10)
.elasticX(true)
.label(function (d) {return d.key == ''?'Not Assigned':d.key});

However, IF you want a large number of dimensions to interact on the crossfilter and you just don't want that data in any of the dimensions, then remove the values from the crossfilter. https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_remove

HTH

Justin Brumley

unread,
Jun 12, 2014, 10:10:44 AM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com
The data that I want my choropleth to display is already formatted for a single state's counties. It does not have data for any other states. The problem isn't getting the data to work with the map or anything. But my geojson file is for the entire United States. I want some way to just not render any other states, because I am running into the issue of, whenever the user clicks a county, it will highlight as well as all other counties with the same name in other states. I need a way to clip other states out and only render one state.

Sorry, its hard to explain.

Adam Reynolds

unread,
Jun 12, 2014, 10:16:25 AM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com
Nothing says you can't have a crossfilter with JUST that states data in it. 

One solution I used was to use the listeners https://github.com/dc-js/dc.js/blob/master/web/docs/api-1.6.0.md#listeners to generate  another crossfilter derived on the selection on the first crossfilter. You could do something similar.

Note I haven't worked with the choropleth yet so may be completely wrong. Does sound like you have a crossfilter with too much data in it.

Justin Brumley

unread,
Jun 12, 2014, 10:20:01 AM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com
I actually only have one instance of crossfilter, it doesn't have too much data in it, and I actually need all of the data inside it. I am not using a crossfilter at all on the data that is coming in from the geojson.

Basic layout is:

import csv
     crossfilter with csv
     dimension on crossfilter
     group on dimension
          import geojson
               create map

Justin Brumley

unread,
Jun 12, 2014, 10:28:52 AM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com
Here is a picture of what I am getting. What I want, is for only the state of louisiana to be visible.


Gordon Woodhull

unread,
Jun 12, 2014, 11:01:11 AM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com
Can't you just create a separate dimension on states and filter that to just Louisiana, as Adam originally suggested?

Adam Reynolds

unread,
Jun 12, 2014, 11:05:24 AM6/12/14
to Gordon Woodhull, Justin Brumley, dc-js-us...@googlegroups.com
To clarify, create a fake group that ONLY includes Louisiana data.

Justin Brumley

unread,
Jun 12, 2014, 11:06:55 AM6/12/14
to dc-js-us...@googlegroups.com, gor...@woodhull.com, justinbr...@gmail.com
I think I understand what you are saying now. I am just trying to get the filtering to work now. I am struggling a little bit with the call to overlayGeoJson() and what is supposed to go in the first parameter. I think I might have it though. Thanks.

Gordon Woodhull

unread,
Jun 12, 2014, 11:08:01 AM6/12/14
to Adam Reynolds, Justin Brumley, dc-js-us...@googlegroups.com
I don't think you even need a group, never mind a fake group.  
Just create a dimension indexing on state, and then dimension.filter("LA")

Justin Brumley

unread,
Jun 12, 2014, 11:10:39 AM6/12/14
to dc-js-us...@googlegroups.com, awjre...@gmail.com, justinbr...@gmail.com
I think it is a little more complicated than just that though. The data from the geojson looks something like this:

{ "type": "Feature", "properties": { "GEO_ID": "0500000US13265", "STATE": "13", "COUNTY": "265", "NAME": "Taliaferro", "LSAD": "County", "CENSUSAREA": 194.608000 }, "geometry": { " .........

So I'm thinking I'll have to access it like:

dimension.filter(function(d)
{
     return d.properties.STATE === "22";
});

.... but now I keep getting a "d.properties does not exist" error. :/

Gordon Woodhull

unread,
Jun 12, 2014, 11:14:05 AM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com, awjre...@gmail.com
I am suggesting more like

var dim = cf.dimension(function(d) { return d.properties.STATE; });
dim.filter("22");

(modulo inevitable debugging - put breakpoints in those accessor functions!)

I think this will be more efficient, because filterFunction is slower than filtering by key.

Justin Brumley

unread,
Jun 12, 2014, 11:20:21 AM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com, awjre...@gmail.com
If I were to filter out by key like that, how would I be able to pass in the entire dimension when it's time to pass it into the geo overlay function? Because as of right now, I have to pass in data.features into the function. The properties attribute is deeper inside like data.features.properties.

Top of Json:

{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "GEO_ID": "0500000US01001", "STATE": "01", "COUNTY": "001", "NAME": 


Like looking at the top of the geojson, you can see the "features". I have to pass in everything from features into the geoOverlay function, but whenever I create a dimension on it like:

data.dimension(function(d) { return d.features; });

then filter, I always end up with a "too much recursion" error....

Justin Brumley

unread,
Jun 12, 2014, 12:04:46 PM6/12/14
to dc-js-us...@googlegroups.com
I finally found out how to solve this problem is anybody is curious. I completely got away from crossfilter with this one because it was causing a lot of trouble since there was attributes inside an array that was also inside the json.

What I did was, first loop through every element of the features array of the json file...

for(var i = 0; i < statesJson.features.length; i++)
{

From inside here, it was just a simple check to see if the properties attribute of each element was equal to that of louisiana...

if(statesJson.features[i].properties.STATE != "22")

If it resulted to true, that meant I wanted to remove the state from the array, so I used a simple splice on the array, and passed in the remaining features and I got the result I was looking for.

statesJson.features.splice(i--, 1);



Sorry about having an issue that wasn't much to do with crossfilter or dc. ;/

Gordon Woodhull

unread,
Jun 12, 2014, 12:56:59 PM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com, awjre...@gmail.com
Crossfilter really only works well with a flat array of records.

Looks like you probably want that array to be the features from the county topojson, i.e. a record per county.

So I guess that would look like (untested)

var cf = crossfilter(data.features);
var statedim = cf.dimension(function(d) { return d.STATE; });
statedim.filter("22");

Now if you have another dimension by county, you will only see the counties in Louisiana, because all the other states are filtered out.

Of course, if all you ever care about is Louisiana, you also might just do crossfilter(data.features.filter(function(d) { return d.STATE == "22"; }))

from the start, and save some memory/CPU.

Gordon Woodhull

unread,
Jun 12, 2014, 12:59:49 PM6/12/14
to Justin Brumley, dc-js-us...@googlegroups.com, awjre...@gmail.com
Er...

On Jun 12, 2014, at 12:56 PM, Gordon Woodhull <gor...@woodhull.com> wrote:
> var cf = crossfilter(data.features);
> var statedim = cf.dimension(function(d) { return d.STATE; });

d.properties.STATE

> statedim.filter("22");
>
> Now if you have another dimension by county, you will only see the counties in Louisiana, because all the other states are filtered out.
>
> Of course, if all you ever care about is Louisiana, you also might just do crossfilter(data.features.filter(function(d) { return d.STATE == "22"; }))

d.properties.STATE

Justin Brumley

unread,
Jun 12, 2014, 2:50:42 PM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com, awjre...@gmail.com
I posted about getting it working but it didn't seem to show up...

But year, I finally figured out the best way to do it. I went ahead and stayed away from crossfilter for a bit because it was only causing trouble for my features array. What I did was looped the length of the features array and removed any elements that weren't apart of Louisiana ('22') by using a splice.

Heres what is looks like: 

for(var i = 0; i < statesJson.features.length; i++)
{
if(statesJson.features[i].properties.STATE != "22")
{
statesJson.features.splice(i--, 1);
};
};

Just in case you wanted to know how I ended up doing it. Thanks for the help though. I guess I was just to committed to crossfilter to look for a simpler way to do it. >:|

Justin Brumley

unread,
Jun 12, 2014, 2:51:20 PM6/12/14
to dc-js-us...@googlegroups.com, justinbr...@gmail.com, awjre...@gmail.com

Final Result:

Reply all
Reply to author
Forward
0 new messages