Ответ 1
В Shiny вы можете практически сделать что угодно, так как вы можете создать свой собственный input и output bindings – поэтому ответ на ваш вопрос - да, то, что вы спрашиваете, возможно. Скажем, у вас есть кадр данных, который вы отправляете на веб-страницу для просмотра пользователем. Например, вы хотите, чтобы пользователи просто щелкали по ячейке, если она была удалена, которая должна быть удалена (заменена на NA
).
Скажем, что кадр данных выглядит так:
x <- data.frame(Age = c(10, 20, 1000), Weight = c(120, 131, 111))
x
# Age Weight
# 10 120
# 20 131
# 1000 111
От блестящего вы создадите обычную HTML-таблицу, которая может выглядеть примерно так, если она отображается на веб-странице:
<table class="outlier-finder" id="outliers">
<tr>
<td>Age</td>
<td>Weight</td>
</tr>
<tr>
<td>10</td>
<td>120</td>
</tr>
<tr>
<td>20</td>
<td>131</td>
</tr>
<tr>
<td>1000</td>
<td>111</td>
</tr>
</table>
Теперь вырвите jQuery и привяжите событие click, чтобы при щелчке ячейки вы могли записать номер строки и столбца (см. здесь), а затем заменить это ячейка с NA
в Shiny. Ваша привязка к вводу может выглядеть примерно так (См. Здесь информацию о том, что происходит здесь):
$(document).on("click", ".outlier-finder td", function(evt) {
// Identify the clicked cell.
var el = $(evt.target);
// Raise an event to signal that the something has been selected.
el.trigger("change");
});
var cell_binding = new Shiny.InputBinding();
$.extend(cell_binding, {
find: function(scope) {
return $(scope).find(".outlier-finder td");
},
getValue: function(el) {
// Get the row and cell number of the selected td.
var col = el.parent().children().index(el);
var row = el.parent().parent().children().index(el.parent());
var result = [row, col];
return result;
},
setValue: function(el, value) {
$(el).text(value);
},
subscribe: function(el, callback) {
$(el).on("change.cell_binding", function(e) {
callback();
});
},
unsubscribe: function(el) {
$(el).off(".cell_binding");
}
});
Shiny.inputBindings.register(cell_binding);
Здесь много чего происходит, но обычно эти привязки ввода довольно похожи друг на друга. Самое главное - это функция setValue()
. То, что должно происходить там (это непроверено), - это номер строки и столбца выбранной ячейки, записанный и отправленный обратно на сервер.
Затем из Shiny вы просто сделаете что-то вроде:
updateData <- reactive({
# Get selection
remove_outlier <- as.integer(RJSONIO::fromJSON(input$outliers))
if (!is.null(remove_outlier)) {
# Remove that outlier.
x[remove_outlier[1], remove_outlier[2]] <- NA
}
return(x)
})
output$outliers <- renderText({
# Update x.
current_x <- updateData()
# Write code to output current_x to page.
# ...
# ...
})
Вам, вероятно, потребуется также создать привязку вывода для выходных $outliers. Очевидно, это упрощенный код, вам нужно будет применить проверку ошибок и т.д.
Это просто пример. На самом деле у вас, вероятно, не будет Shiny обновление вашего фрейма данных каждый раз, когда пользователь внесет изменения. Вы хотели бы иметь какую-то кнопку отправки, чтобы после того, как пользователь выполнил все свои изменения, они могут быть применены.
Я даже не тестировал ни один из этих удаленно, поэтому почти наверняка есть некоторые ошибки. Но поскольку вы просто задавали теоретический вопрос, я не слишком много проверял. В общем, общая тактика должна работать. С помощью привязок ввода вы можете получить что-либо с веб-страницы обратно на сервер и наоборот с привязкой к выводам. Может быть, говорить "что-нибудь" - это растяжка? но вы можете многое сделать.