使用大型 csv:如何删除破折号回调中的冗余下拉选项?

Using a large csv: how to remove redundant dropdown options in a dash callback?

我正在使用一个包含州、县的大型 csv 文件,然后是每个县特定的一堆数据。在 Dash 中,我尝试使用一系列回调来允许用户按州 select,然后按县,然后他们根据需要添加或删除特定于县的数据。我的 df:

df = [dict(State="CO", County="Franklin", Task="Job A", Start='2020-01-01', Finish='2020-02-28'),
      dict(State="CO", County="Franklin", Task="Job A", Start='2020-03-01', Finish='2020-04-28'),
      dict(State="CO", County="Franklin", Task="Job B", Start='2020-05-05', Finish='2020-06-15'),
      dict(State="CO", County="Franklin", Task="Job B", Start='2020-06-05', Finish='2020-07-15'),
      dict(State="CO", County="Franklin", Task="Job B", Start='2020-08-05', Finish='2020-09-15'),
      dict(State="CO", County="Franklin", Task="Job B", Start='2020-10-05', Finish='2020-12-15'),
      dict(State="CO", County="Wise", Task="Job A", Start='2020-01-01', Finish='2020-02-28'),
      dict(State="CO", County="Wise", Task="Job A", Start='2020-03-01', Finish='2020-04-28'),
      dict(State="CO", County="Wise", Task="Job B", Start='2020-05-05', Finish='2020-06-15'),
      dict(State="CO", County="Wise", Task="Job B", Start='2020-06-05', Finish='2020-07-15'),
      dict(State="CO", County="Wise", Task="Job B", Start='2020-08-05', Finish='2020-09-15'),
      dict(State="CO", County="Wise", Task="Job B", Start='2020-10-05', Finish='2020-12-15'),

使用下拉回调,我使用以下内容填充下拉选项:

dcc.Dropdown(id='location-choice',
             options=[{'label': x['County'], 'value': x['County']} for x in df],
             other attributes, etc)             

但它会为我的州下拉列表中的 csv 文件中的每一行加载每个“CO”(此示例将在下拉列表中提供 12 个相同的 CO)和我的县下拉列表中的 csv 文件中的每个县行(此示例将在下拉列表中提供 6 个富兰克林和 6 个智者。

如果 selected 并加载与我图表上的 selection 相关的所有行,它们都有效(例如:selecting CO 和 Franklin 仍然加载作业 A 和所有 4 个工作 B) 这就是我想要的。

总结:如何从下拉列表中删除冗余选项,同时仍保留 df 中的那些行以用于绘图目的?

谢谢!

编辑:感谢 coralvanda。他们的解决方案解决了位置和任务 selection 中的冗余下拉选项,但我很难遵循更新时间线图所需的更改。以下是我更新我的图表的函数,它在没有 pandas 的情况下运行良好(需要县和任务 selection,只是有冗余的 selection 选项),所以我想我只是想治愈我对pandas的无知

    def build_graph(location_selected, job_selected):

        print(job_selected)
        print(location_selected)

        dff = [d for d in df if d['County'] in location_selected] 
        dff = [d for d in dff if d['Task'] in job_selected]


        fig = px.timeline(
            data_frame=dff,
            x_start='Start',
            x_end='Finish',
            y='Task',

我收到以下错误:

line 130, in <listcomp>
     dff = [d for d in df if d['County'] in location_selected]
     TypeError: string indices must be integers

因为我的 csv 文件有这些列:[State,County,Task,Tool,Start,End],我改为:

        dff = [d for d in df if d[1] in location_selected] 
        dff = [d for d in dff if d[2] in job_selected]

运行此时报错如下:

ValueError: Value of 'y' is not the name of a column in 'data_frame'. Expected one of [] but received: Task

从这里我尝试了几个选项,但是在之前和之后使用 using print(dff.shape):

        print(job_selected)
        print(location_selected)
        dff=df
        print(df.shape)
        print(dff.shape)
        dff = [d for d in df if d[1] in location_selected]
        print(dff.shape)
        dff = [d for d in dff if d[2] in job_selected]
        print(dff.shape)

显示 dff 行为异常:

['Job A', 'Job B']
['Franklin']
(4101, 6)
[]
[]

如果我选择另一个县:

['Job A', 'Job B']
Bath
(4101, 6)
['State', 'Start']
[]

如果我更改 job_selected,它会以适当更改的列表作为响应。

如果您能帮助我解决最后一部分,我们将不胜感激。谢谢!!

使用pandas中的.unique()方法。你给出的例子是使用县,所以我会坚持下去,但同样的事情应该适用于其他下拉菜单。我猜这是列名。

dcc.Dropdown(id='location-choice',
             options=[{'label': x, 'value': x} for x in df['County'].unique(),
             other attributes, etc)   

如果这还不够,您可能需要使用 pandas tolist() 方法将其转换为列表,如下所示:

df['County'].unique().tolist()

我在本地没有运行这个,所以如果它不起作用请告诉我,我会再看看。

编辑:我发现您的示例中没有 pandas.DataFrame CSV。如果您还没有这样做,您可以轻松地执行 df = pandas.read_csv() 并传入文件位置。然后你可以在数据框上使用 pandas 方法。

编辑 2: 习惯 pandas 可能需要一点时间,但我相信付出的努力是值得的。如果我正确理解了你的新问题,听起来你需要 select 基于用户下拉列表 select 离子的数据框子集。你可以这样做:

dff = df[df['County'].isin(location_selected) & df['Task'].isin(job_selected)]