Применение .filter () к ColumnDataSource в обратном вызове Bokeh JS - PullRequest
0 голосов
/ 03 апреля 2020

Проблема: я не могу применить функцию фильтра к columndatasource, и даже после применения она дает весь мой полный массив. Мое отсутствие знакомства с JS усугубляет ситуацию.

Поэтому я пытался воспроизвести результаты отсюда:

https://discourse.bokeh.org/t/possible-to-use-customjs-callback-from-a-button-to-animate-a-slider/3985

Но используя мой собственный источник данных.

Вот код для JS Обратный вызов:

# Create slider callback
SliderCallback = CustomJS(args = dict(sliceCDS=sliceCDS, fullCDS=fullCDS, indexCDS=indexCDS), code = """
    const new_value = cb_obj.value;

    // Take the 'Slice' column from the full data
    const slice_col = fullCDS.data['Slice'];

    // Select only the values equal to the new slice number
    const mask = slice_col.map((item) => item==new_value);

    sliceCDS.data['x'] = fullCDS.data['x'].filter(item => mask);
    sliceCDS.data['y'] = fullCDS.data['y'].filter(item => mask);
    sliceCDS.data['label'] = fullCDS.data['label'].filter(item => mask);

    //console.log('Here is the data');
    console.log(sliceCDS.data['x']);
    console.log(sliceCDS.data['y']);
    console.log(sliceCDS.data['label']);


    // Update the sliceCDS
    sliceCDS.change.emit();
    """)

# Set up slider
slider = bokeh.models.Slider(title="Slice view number: ",start=0, end=49,value=0,step=1)
slider.js_on_change('value', SliderCallback)

Вот sliceCDS (входной сигнал для JS обратного вызова):

{'x': 0   -0.001215
0    0.001454
0   -0.000191
0   -0.000377
0   -0.000008
       ...   
0    0.001993
0    0.002045
0    0.002220
0   -0.003160
0   -0.000088
Name: x, Length: 1797, dtype: float64, 'y': 0    0.000745
0    0.000171
0   -0.000004
0    0.000268
0    0.000535
       ...   
0   -0.000417
0    0.002719
0   -0.000269
0    0.000766
0    0.000250
Name: y, Length: 1797, dtype: float64, 'label': 0    0
0    0
0    0
0    0
0    0
    ..
0    9
0    9
0    9
0    9
0    9
Name: label, Length: 1797, dtype: int64, 'Slice': 0    0
0    0
0    0
0    0
0    0
    ..
0    0
0    0
0    0
0    0
0    0
Name: Slice, Length: 1797, dtype: int64}

Вот fullCDS (вход для JS обратного вызова):

{'x': 0     -0.001215
0      0.001454
0     -0.000191
0     -0.000377
0     -0.000008
        ...    
49   -12.208837
49   -11.620906
49   -16.709465
49   -13.481855
49   -12.067336
Name: x, Length: 89850, dtype: float64, 'y': 0      0.000745
0      0.000171
0     -0.000004
0      0.000268
0      0.000535
        ...    
49    28.264780
49    27.768742
49    27.019316
49    27.537040
49    24.889742
Name: y, Length: 89850, dtype: float64, 'label': 0     0
0     0
0     0
0     0
0     0
     ..
49    9
49    9
49    9
49    9
49    9
Name: label, Length: 89850, dtype: int64, 'Slice': 0      0
0      0
0      0
0      0
0      0
      ..
49    49
49    49
49    49
49    49
49    49
Name: Slice, Length: 89850, dtype: int64}

С помощью приведенного выше кода я не могу обновить sliceCDS. Он по-прежнему содержит все 89850 строк, тогда как после применения .filter () он должен содержать только 1797. РЕДАКТИРОВАТЬ: по предложению, я также попробовал следующее в функции:

sliceCDS.data['x'] = fullCDS.data['x'].filter((item,idx) => mask[idx]);

, и это дает мне следующую ошибку:

VM499:17 Uncaught TypeError: Cannot read property 'filter' of undefined

и пробовал с этим также:

sliceCDS.data['x'] = fullCDS.data['x'].filter((item,0) => mask[0]);

, который дал мне эту ошибку:

VM505:31 Uncaught SyntaxError: Invalid destructuring assignment target

Но если я попробую метод по приведенной выше ссылке, с именами столбцов в моих источниках данных columndatas как Line1 для x, Line2 для y и Line3 для label:

// Update the data for sliceCDS with a slice of data from fullCDS
    for(i=1; i<3; i++){
        sliceCDS.data['Line' + i.toString()] = fullCDS.data['Line' + i.toString()].filter((item,i) => mask[i]);
    }

Приведенный выше код работает просто отлично.

Но почему код для случая, упомянутый в начале, не работает? Я уверен, что что-то не так с тем, как я использую .filter ().

1 Ответ

1 голос
/ 03 апреля 2020

У вас есть это выражение.

fullCDS.data['x'].filter(item => mask);

item => mask всегда возвращает mask, независимо от того, что item. В JavaScript массив всегда истинен, независимо от содержимого.

Второй аргумент функции фильтра - это индекс элемента. Попробуйте вместо этого использовать (item, idx) => mask[idx] лямбда.

...