Folium:在地图中添加GeoJson时进行颜色映射

5
我在Python代码中有一个循环,用于向我的Folium地图添加功能。每个功能都包含在一个字典中(称为产品),每个功能都有一个参数字典(GeoJson字符串和属性)。我想根据其中一个参数的值对该功能进行着色。
我首先创建了该参数唯一值的列表。然后我将每个唯一值映射到一种颜色:
orb_list = [value['relativeorbitnumber'] for key, value in products.items()]
orb_list = list(set(orb_list))

color_cycle = cycler(color=['#8e0038', '#8e0073', '#59008e'], fillColor=['#8e0038', '#8e0073', '#59008e'])

orb_colors=dict([[i, sty] for i, sty in zip(orb_list, cycle(color_cycle))])

接下来,我创建一个循环,在循环中获取特征参数值对应的颜色和填充颜色,并在样式函数中使用它们:

for key,value in products.items():
    footprint = json.dumps(wkt.loads(products[key]['footprint']))
    fillColor = orb_colors[products[key]['relativeorbitnumber']]['fillColor']
    color = orb_colors[products[key]['relativeorbitnumber']]['color']
    feat = folium.GeoJson(footprint,
               style_function=lambda x: {'fillColor':fillColor,'color':color},
               highlight_function=lambda feature: {'fillcolor':'green','color':'green'},
               name='Footprint')

    feat.add_to(mapa)

我原以为这个方法可以奏效,但是我的循环中似乎所有的特征都被最后一次“fillColor”和“color”所着色。有人能解释一下这是为什么吗?我猜想所有的特征直到所有循环结束后才被渲染,因此最后一个“color”和“fillColor”的值被用于所有的特征。你能建议如何修改我的代码来解决这个问题吗?或者也许我走了一条错误的路,你能提供一个更加简洁的方法吗?

1个回答

12

你遇到了Python中一个常见的陷阱 闭包

你传递给例如style_function的函数不会立即在循环中执行,而是稍后执行。在那个时候,fillColor将从外部作用域检索(因为它没有在由lambda表达式创建的内部作用域中定义),在这个点上,它将具有最后一个值。

为了演示正在发生的事情:

In [1]: out = []
   ...: for k in ('a', 'b', 'c'):
   ...:     l = lambda: k
   ...:     out.append(l)
   ...: [l() for l in out]
Out[1]: ['c', 'c', 'c']
为了避免这种情况,您可以将变量的(当前)值作为lambda表达式创建的函数的默认参数传递,以便在稍后执行该函数时使用该值:

要实现此目的,您可以将变量的(当前)值作为默认参数传递给lambda表达式创建的函数,以便稍后在执行该函数时使用该值:

In [2]: out = []
   ...: for k in ('a', 'b', 'c'):
   ...:     l = lambda k=k: k
   ...:     out.append(l)
   ...: [l() for l in out]
Out[2]: ['a', 'b', 'c']

或者在您的代码中:

for key, value in products.items():
    footprint = json.dumps(wkt.loads(products[key]["footprint"]))
    fillColor = orb_colors[products[key]["relativeorbitnumber"]]["fillColor"]
    color = orb_colors[products[key]["relativeorbitnumber"]]["color"]
    feat = folium.GeoJson(
        footprint,
        style_function=lambda x, fillColor=fillColor, color=color: {
            "fillColor": fillColor,
            "color": color,
        },
        highlight_function=lambda feature: {"fillcolor": "green", "color": "green"},
        name="Footprint",
    )

    feat.add_to(mapa)

这应该可以解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接