如何在熊猫数据框输出中定义索引或点击行数?
Posted
技术标签:
【中文标题】如何在熊猫数据框输出中定义索引或点击行数?【英文标题】:How could define index or number of clicked row in pandas dataframe output? 【发布时间】:2019-09-11 04:59:25 【问题描述】:我想在 ipywidgets 上制作一些表格,在其输入中显示特定行的 pandas 数据框的值。
为了使行选择和以更具交互性的形式显示,我需要以某种方式单击显示的数据框。实际上,我希望能够识别最后点击的数据框行的索引或数量。
附言 我见过像 ipysheet 和其他工具这样的工具,但我认为它们仍然太新,尽管 ipysheet 将来可能会非常强大。 所以这些工具不适用于这项任务。
【问题讨论】:
对社区来说似乎是个棘手的问题) 你如何使用这个ipywidgets?您使用 Excel 之类的表单吗?你在 jupyter 中使用它吗? 【参考方案1】:我遇到了类似的问题,qgrid
对我来说太过分了。
在 jupyter 中的工作(灵感来自 add click feature on each row in html table):
注入的脚本将处理程序添加到数据帧表的每个单元格(由id='T_table'
到Styler.set_uuid
函数标记)。
当一个单元格被点击时典型的处理程序:
查找指定的输入元素(隐藏并由占位符“未定义”标记),
为单击的单元格的类名设置找到的输入的 value 属性,
触发“更改”事件。之后,点击单元格的类名(pandas 使它们包含必要的行/列信息)可用于 ipywidgets 框架,并可在 python 中处理。
备注:
在调用脚本之前需要一定的超时时间。对于更大的表,所需的超时时间可能会更大。
逻辑有点复杂,因为我使用的将js-values引入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])
【讨论】:
这是一个非常好的实现,我只是想知道被点击的行是否可以在被点击后保持突出显示【参考方案2】:你试过qgrid吗?
它在 github 上的定义是:一个交互式网格,用于在 Jupyter 笔记本中排序、过滤和编辑 DataFrames。
【讨论】:
【参考方案3】:带有 on_click 事件处理程序的 Jupyter 中的 Pandas 输出
点击行时:
行高亮 提供给 on_click 的行号 以打印行号和内容为例基于@dzenny 的回答
import pandas as pd
import ipywidgets as wgt
from IPython.display import display, HTML
import re
# javascript-part
script = """
<style>tr.selected background-color:#00FFFF!important</style>
<script>
(function ()
var input = document.evaluate("//input[contains(@placeholder,'undefined')]", document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
input.setAttribute("hidden","");
var table = document.querySelector("#T_table");
var rows = Array.from(table.querySelectorAll('tbody > tr'));
var cells = Array.from(table.querySelectorAll("td"));
for (var i=0; i < cells.length; i++)
var createClickHandler = function(cell)
return function()
input.value = cell.className;
var event = new Event('change', bubbles: true );
input.dispatchEvent(event);
rows.forEach(el => el.classList.remove('selected'))
cell.parentElement.classList.add('selected')
cells[i].onclick = createClickHandler(cells[i]);
;
)();
</script>
"""
# ipywidgets-part
df = 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 = df.style.set_uuid('table')
def on_click(change):
cls = change['new'].split(' ')
row = int(re.search(r'\d+',cls[1]).group(0))
print('row=', row)
print(df.iloc[[row]])
click_handler = wgt.Text(placeholder='undefined')
click_handler.observe(on_click,names=['value'])
out = wgt.Output()
with out: display(html)
display(out,click_handler,HTML(script))
【讨论】:
真的很有帮助。我在 JupyterLab 3.2.5 中没有看到打印,但是在阅读了 GitHub 上的第 2148 期后,我发现我需要重新排序代码,因此在out
之前创建 on_click
并在定义回调之前添加 @out.capture()
所以显示回调中的打印。以上是关于如何在熊猫数据框输出中定义索引或点击行数?的主要内容,如果未能解决你的问题,请参考以下文章