简体   繁体   English

Altair choropleth 地图,基于折线图选择的颜色突出显示

[英]Altair choropleth map, color highlight based on line chart selection

I am plotting a choropleth map colored by the field Passenger_0_ and a line chart showing the evolution of Passenger_0_ throughout a day by zone .我正在绘制由区域Passenger_0_着色的等值线图和显示Passenger_0_在一天中按zone的演变的折线图。

I would like to select a line ( zone ) in the line chart and have it highlighted in the map and vice versa (select a zone in the map and have it highlighted in the line chart).我想在折线图中选择一条线( zone )并在地图中突出显示它,反之亦然(在地图中选择一个区域并在折线图中突出显示)。

For now, I am able to change the whole color of the map when selecting the line, but have no clue of how to only change the color of the selected area.现在,我可以在选择线时更改地图的整体颜色,但不知道如何仅更改所选区域的颜色。

I would appreciate any help.我将不胜感激任何帮助。

In order to reproduce the sample you need to download these two files:为了重现示例,您需要下载这两个文件:

output_data.csv 输出数据.csv

taxi_zones.geojson 出租车区域.geojson

Then run this piece of code to get a GeoDataFrame named long_df :然后运行这段代码以获取名为long_df

import altair as alt
import pandas as pd
import geopandas as gpd
import json

geo_json_file_loc= './taxi_zones.geojson'

with open(geo_json_file_loc) as json_data:
    data = json.load(json_data)
    
gdf = gpd.GeoDataFrame.from_features((data))
gdf = gdf[gdf['borough']=='Manhattan']
gdf = gdf[['location_id','zone','geometry']]
gdf = gdf.rename(columns={'location_id':'LocationID'})
gdf['LocationID'] = pd.to_numeric(gdf['LocationID'])

output_data = pd.read_csv('./output_data.csv',sep=',')

def load_taxis_data(output_data, shape_data):
    df_to_visualize = shape_data.copy()
    pickups = output_data.groupby(['hour','dayofweek','LocationID']).sum()
    listofdays = pd.unique(output_data['dayofweek'])

    for hour in range(24):
        for dayofweek in listofdays:
            # get pickups for this hour and weekday
            p = pd.DataFrame(pickups.loc[(hour, dayofweek)]).reset_index()
        
            # add pickups to the Taxi Zones DataFrame       
            df_to_visualize = pd.merge(df_to_visualize, p, on="LocationID", how="left").fillna(0)
            # rename column as per day and hour
            df_to_visualize.rename(columns={"pickups" : "Passenger_%d_%d"%(dayofweek, hour)}, inplace=True)
    return df_to_visualize        

gdf_merged = load_taxis_data(output_data, gdf)

# drop unwanted days
for hour in range(24):
    for dayofweek in [5,6]:
        column_to_drop = "Passenger_%d_%d"%(dayofweek, hour)
        gdf_merged.drop([column_to_drop], axis=1, inplace=True)

gdf_merged.reset_index(level=0, inplace=True)

long_df = pd.wide_to_long(gdf_merged, ["Passenger_0_"], i='index', j="hour")
long_df = long_df.reset_index()

Once you got long_df this is the code for the plots:获得long_df这是绘图的代码:

dict_json = json.loads(long_df[long_df['hour']==0].to_json())

colours_obj = alt.Color('properties.Passenger_0_:Q',
              scale=alt.Scale(scheme='yelloworangered'),
             title = "Pickups")

sel_line_hover = alt.selection_single(on='mouseover', empty='none')
sel_line_col = alt.selection_single()
sel_line_size = alt.selection_single(empty='none')

base = alt.Chart(alt.Data(values=dict_json['features'])).mark_geoshape(
    stroke='black',
    strokeWidth=1
    ).encode(
    color=alt.condition(sel_line_col, colours_obj, alt.value('lightgray')),
    tooltip = ['properties.zone:O',
               'properties.Passenger_0_:Q']
    ).properties(
    width=350,
    height=750,
    ).add_selection(
    sel_line_col
    )

line = alt.Chart(long_df).mark_line().encode(
    x='hour',
    y='Passenger_0_',
    color=alt.condition(sel_line_hover|sel_line_col, 'zone', alt.value('lightgray')),
    size=alt.condition(sel_line_hover|sel_line_size, alt.value(4),alt.value(1)),
    tooltip = ['zone:O']
    ).properties(
    width=250,
    height=750,
    ).add_selection(
    sel_line_hover,sel_line_col,sel_line_size
    )

base | line

And this is what the plot does:这就是情节的作用: 在此处输入图片说明

Thank you in advance for your help!预先感谢您的帮助!

Here is a general example of how to achieve two-way interactivity in Altair, using data from the sample repos only.以下是如何在 Altair 中实现双向交互的一般示例,仅使用来自示例存储库的数据。 The key is to set the feature that should be filtered by the selection even via fields parameter when creating the selection.关键是在创建选择时设置应该被选择过滤的特征,即使是通过fields参数。 Then you add this selection and the corresponding condition to the same encoding of both the plots.然后您将此选择和相应的条件添加到两个图的相同编码中。

import altair as alt
from vega_datasets import data


state_pop = data.population_engineers_hurricanes()[['state', 'id', 'population']]
state_map = alt.topo_feature(data.us_10m.url, 'states')

click = alt.selection_multi(fields=['state'])

choropleth = (alt.Chart(state_map).mark_geoshape().transform_lookup(
    lookup='id',
    from_=alt.LookupData(state_pop, 'id', ['population', 'state']))
.encode(
    color='population:Q',
    opacity=alt.condition(click, alt.value(1), alt.value(0.2)),
    tooltip=['state:N', 'population:Q'])
.add_selection(click)
.project(type='albersUsa'))

bars = (
    alt.Chart(
        state_pop.nlargest(15, 'population'),
        title='Top 15 states by population').mark_bar().encode(
    x='population',
    opacity=alt.condition(click, alt.value(1), alt.value(0.2)),
    color='population',
    y=alt.Y('state', sort='x'))
.add_selection(click))

choropleth & bars

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM