使用 Panel Select Widget 从下拉菜单中选择后,从文件路径交互式创建 DataFrame

Create DataFrame from filepath interactive after choosing from Drop Down menu with Panel Select Widget

我想要一个带面板的 Select 小部件,我可以在其中 select 来自字典的 ID。 ID 是键,值是存储表格数据的 geojson 文件的文件路径。在我交互式地选择一个 id 之后,应该加载数据框。我的问题是它只在我第一次选择一个值时起作用。如果我尝试 select 另一个,数据框将不会更新。 pandas 是否有可能在我选择新 ID 后更新 read_file 功能?

# Import modules
from glob import glob
import geopandas as gpd
import panel as pn
# Initializes the pyviz notebook extension to allow plotting with bokeh and enable comms
pn.extension()

# Store all filepaths within a list
filespaths = ['C://Users/USER/Desktop/Master_Irrigation/03_GIS/ground_trouth/sentinel_ismn_data\1018_15.15537_48.1521.geojson',
 'C://Users/USER/Desktop/Master_Irrigation/03_GIS/ground_trouth/sentinel_ismn_data\1026_15.15472_48.15053.geojson']

# Create Station id linked with filepath
ids = [x.split('\')[-1].split('_')[0] for x in filespaths]
#Create dict with Ids as key and filepaths as value
files = dict(zip(ids,filespaths ))

# Widget to select station id, widget.value stores filepath
id_selector = pn.widgets.Select(name='ISMN Station ID', options=files)

# Load file into GeoPandas DataFrame
gdf = gpd.read_file(id_selector.value)
id_selector

编辑: 我知道一种方法是将所有数据加载到一个 DataFrame

gpd = gpd.tools.util.pd.concat(map(gpd.read_file, paths), ignore_index=True)

但是对于数百个包含数千行的文件,这会导致性能问题。

  • 从根本上说,您需要考虑您的范式。您正在使用基于事件的范例,因此需要 回调 来响应您的事件(从下拉列表中选择的文件)
  • 我没有使用过 面板 并且无法使用回调。因此,鉴于您的运行时环境是 jupyter(基于评论)
  • ,因此切换到 ipwidgets
  • 以此响应事件并使用选定的文件加载 gdf。通过使用 glob() 查找 geojson 文件
  • 合成了一个 MWE
import ipywidgets as widgets
from pathlib import Path
from glob import glob
import geopandas as gpd

# Store all filepaths within a list
# filespaths = ['C://Users/USER/Desktop/Master_Irrigation/03_GIS/ground_trouth/sentinel_ismn_data\1018_15.15537_48.1521.geojson',
#  'C://Users/USER/Desktop/Master_Irrigation/03_GIS/ground_trouth/sentinel_ismn_data\1026_15.15472_48.15053.geojson']
# well my filesystem is different,  get some geojson files
filespaths = list(set(Path.cwd().glob("**/*.geojson")) -  set(Path.cwd().glob(".ipynb_checkpoints/*.geojson")))

# Create Station id linked with filepath
# ids = [x.split('\')[-1].split('_')[0] for x in filespaths]
# my filenames don't contain any underscores ...
ids = list(range(len(filespaths)))
#Create dict with Ids as key and filepaths as value
files = dict(zip(ids,filespaths ))

gdf = None

# useful for debug....
out = widgets.Output(layout={"border": "1px solid black"})
out.append_stdout("Output appended with append_stdout\n")

# use ipwidgets instead
id_selector = widgets.Dropdown(
    options=[(k,v) for k,v in files.items()],
    description='ISMN Station ID:',
    disabled=False,
)

# the key a callback on value change....
@out.capture()
def changed(v):
    global gdf
    if v['type'] == 'change':
        print(v["new"])
        gdf = gpd.read_file(str(v["new"]))
id_selector.observe(changed, names="value")

widgets.VBox([id_selector, out])