我想在ipywidgets上做一些形式,在其输入中显示熊猫数据框特定行的值。
要使行选择和表单显示更具交互性,我需要以某种方式处理在显示的数据框中的单击。实际上,我希望能够识别索引或数据框最后点击的行数。
PS
我见过像ipysheet等工具,但我认为它们仍处于新生阶段,尽管ipysheet将来可能会非常强大。
因此,这些工具不适用于此任务。
答案 0 :(得分:1)
我有类似的问题,qgrid
对我来说太过分了。
jupyter中的工作(受add click feature on each row in html table启发):
注入的脚本将处理程序添加到数据框表的每个单元格中(通过id='T_table'
至Styler.set_uuid
函数标记)。
单击单元格时的典型处理程序:
查找指定的输入元素(由占位符“ undefined”隐藏并标记),
为找到的单元格的类名称设置找到的输入的value属性,
之后,ipywidgets框架可以使用被单击单元格的类名(熊猫使它们包含必要的行/列信息),并且可以在python中进行处理。
备注:
在调用脚本之前,某些超时是必需的。对于更大的桌子,所需的超时可能会更大。
逻辑有点复杂,因为将js值带入我使用的python世界的方法是通过ipywidgets.Text
。
添加了2.1项,以防在启动后重新呈现DOM。
import pandas as pd
import ipywidgets as wgt
from IPython.display import display, HTML
import re
# javascript-part
script = """
<script>
var input
var xpath = "//input[contains(@placeholder,'undefined')]";
function addHandlers() {
input = document.evaluate(xpath, document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
input.setAttribute("hidden","");
var table = document.querySelector("#T_table");
var headcells = [].slice.call(table.getElementsByTagName("th"));
var datacells = [].slice.call(table.getElementsByTagName("td"));
var cells = headcells.concat(datacells);
for (var i=0; i < cells.length; i++) {
var createClickHandler = function(cell) {
return function() {
input = document.evaluate(xpath, document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
input.value = cell.className;
var event = new Event('change', { bubbles: true });
input.dispatchEvent(event);
}}
cells[i].onclick = createClickHandler(cells[i]);
};
}
window.onload = setTimeout(addHandlers, 500);
</script>
"""
display(HTML(script))
# ipywidgets-part
newdf = pd.DataFrame(data={
'1': [11,21,31,41], '2': [12,22,32,42], '3': [13,23,33,43],
'4': [14,24,34,44], '5': [15,25,35,45], '6': [16,26,36,46],
'7': [17,27,37,47], '8': [18,28,38,48], '9': [19,29,39,49],
'10': [110,210,310,410],'11': [111,211,311,411],
})
html = newdf.style.\
set_uuid('table')
def on_change(change):
cls = change['new'].split(' ')
if len(cls) == 2:
place.value, row.value = cls
col.value = '0'
elif len(cls) == 3:
place.value, txtrow, txtcol = cls
res = re.search(r'\d+',txtrow).group(0)
row.value = str(int(res)+1)
res = re.search(r'\d+',txtcol).group(0)
col.value = str(int(res)+1)
else:
place.value, row.value, col.value = ['unknown']*3
status = wgt.Text(placeholder='undefined',layout={'font-size':'6px'})
status.observe(on_change,names=['value'])
table = wgt.Output()
with table: display(html)
layout = {'width':'192px'}
row = wgt.Text(layout=layout,description='row')
col = wgt.Text(layout=layout,description='col')
place = wgt.Text(layout=layout,description='place')
body = wgt.HBox([table,wgt.VBox([place,row,col])])
wgt.VBox([body,status])
答案 1 :(得分:0)
您尝试过qgrid吗?
在github上的定义是:用于在Jupyter笔记本中排序,过滤和编辑DataFrame的交互式网格。