如何将 CSV 文件加载到 QTreeView 中?
How can I load a CSV file into a QTreeView?
注意:我是一个完全的初学者。
我正在使用 pandas 数据框导入我从以下 table 转换而来的 csv 文件。我需要将 csv 文件加载到 QTreeView 中,但一直无法这样做。
输出格式应为:
我将不得不在某个时候检索“比例类型”,所以我想以某种方式将它标记到该项目,但我不确定这是否可能。我尝试将我的数据转换为 pandas 数据框并加载;直接用 csv 加载数据;并把它转换成一本没有运气的字典。
我可以 hard-code 输入该数据,但我更愿意使用 csv,因为我以后可以轻松更改它。
目前正在使用:
model.setHeaderData(0,Qt.Horizontal,"Category")
model.setHeaderData(1,Qt.Horizontal,"Sub Category")
model.setHeaderData(2,Qt.Horizontal,"Test")
self.ui.tv.setModel(model)
self.SetContent(model)
def SetContent(self, model):
self.ui.tv.setModel(model)
i=0
for k,featuretype in features.items():
parent1 = QStandardItem('{}'.format(k[1]))
for item in featuretype:
child = QStandardItem(item[0])
if len(item[1])>0:
for listitem in item[1]:
gchild=QStandardItem(listitem)
child.appendRow(gchild)
parent1.appendRow(child)
model.setItem(i,0,parent1)
self.ui.tv.setFirstColumnSpanned(i,self.ui.tv.rootIndex(),True)
i+=1
这仅适用于硬键控值,例如:
features = {('POLYGON', 'SLPR'): [('ONE WAY', ['NO', 'YES','maybe'], 'List', 3), ('CLASS', ['INTERSTATE', 'PRIMARY', 'RESIDENTIAL', 'SECONDARY', 'SERVICE', 'STATE HWY', 'TERTIARY', 'TRACK', 'US HWY'], 'List', 11)]
但它不适用于我从 csv 或数据框创建的字典 objects,并且出现“字符串索引超出范围错误”。
我也找到了这段代码,这太棒了。但它只给了我重复项和 parents。
reader = csv.reader(f)
for row in reader:
item = QTreeWidgetItem(self.ui.tv, row)
print(row)
下面是一个演示脚本,它应该可以完成您要求的大部分工作。它不能完全产生与第二个屏幕截图相同的布局,但结构是相同的。 csv 文件转换为嵌套 dicts/lists,可以保存到 json 文件。也可以直接加载 json 文件。我假设您的 csv 文件如下所示:
"Test Category","Sub Category","Test Type","Scale Type"
"Premorbid Func.","SIMPLE","Actual","Scale"
"Premorbid Func.","SIMPLE","Predicted","Scale"
"Premorbid Func.","COMPL Montanist","TEST","Scale"
"Premorbid Func.","COMPL Montanist","Actual","Scale"
"Premorbid Func.","COMPL Montanist","Predicted","Scale"
"Intellect","WAIS-IV","WAIS-IV","T Score"
"Intellect","WAIS-IV","VCI","T Score"
"Intellect","WAIS-IV","Similarities","T Score"
"Intellect","WAIS-IV","Vocabulary","T Score"
"Attention","TOVA","RT","Scale"
"Attention","TOVA","RTV","Scale"
"Attention","DV","T","T Score"
树视图如下所示:
演示脚本:
import sys, os, csv, json
from collections import defaultdict
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.buttonLoad = QtWidgets.QPushButton('Load Data')
self.buttonLoad.clicked.connect(self.handleProcessData)
self.buttonSave = QtWidgets.QPushButton('Save Data')
self.buttonSave.clicked.connect(self.handleSaveData)
self.buttonSave.setEnabled(False)
self.tree = QtWidgets.QTreeView()
layout = QtWidgets.QGridLayout(self)
layout.addWidget(self.tree, 0, 0, 1, 2)
layout.addWidget(self.buttonLoad, 1, 0)
layout.addWidget(self.buttonSave, 1, 1)
self.data = None
def loadData(self):
path, ok = QtWidgets.QFileDialog.getOpenFileName(
self, 'Open CSV/JSON', '.', filter='Data Files (*.csv *.json)')
if ok:
with open(path) as stream:
if os.path.splitext(path)[1] == '.json':
self.data = json.load(stream)
else:
reader = csv.reader(stream)
# ignore the header
next(reader)
# convert to nested dicts/lists
self.data = defaultdict(lambda: defaultdict(list))
for record in reader:
self.data[record[0]][record[1]].append(record[2:])
def handleProcessData(self):
self.loadData()
if self.data is not None:
model = QtGui.QStandardItemModel(self.tree)
model.setHorizontalHeaderLabels(('Category', 'Type', 'Scale'))
self.tree.setModel(model)
self.tree.setColumnWidth(0, 200)
root = self.tree.rootIndex()
for row, (text, values) in enumerate(self.data.items()):
category = QtGui.QStandardItem(text)
model.appendRow(category)
self.tree.setFirstColumnSpanned(row, root, True)
for row, (text, values) in enumerate(values.items()):
subcategory = QtGui.QStandardItem(text)
for value in values:
subcategory.appendRow([
QtGui.QStandardItem(),
QtGui.QStandardItem(value[0]),
QtGui.QStandardItem(value[1]),
])
category.appendRow(subcategory)
self.tree.setFirstColumnSpanned(
row, category.index(), True)
self.tree.expandAll()
self.buttonSave.setEnabled(True)
def handleSaveData(self):
path, ok = QtWidgets.QFileDialog.getSaveFileName(
self, 'Save JSON', '.', filter='JSON Files (*.json)')
if ok:
with open(path, 'w') as stream:
json.dump(self.data, stream, indent=2)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Test')
window.setGeometry(600, 100, 540, 480)
window.show()
sys.exit(app.exec_())
注意:我是一个完全的初学者。
我正在使用 pandas 数据框导入我从以下 table 转换而来的 csv 文件。我需要将 csv 文件加载到 QTreeView 中,但一直无法这样做。
输出格式应为:
我将不得不在某个时候检索“比例类型”,所以我想以某种方式将它标记到该项目,但我不确定这是否可能。我尝试将我的数据转换为 pandas 数据框并加载;直接用 csv 加载数据;并把它转换成一本没有运气的字典。
我可以 hard-code 输入该数据,但我更愿意使用 csv,因为我以后可以轻松更改它。
目前正在使用:
model.setHeaderData(0,Qt.Horizontal,"Category")
model.setHeaderData(1,Qt.Horizontal,"Sub Category")
model.setHeaderData(2,Qt.Horizontal,"Test")
self.ui.tv.setModel(model)
self.SetContent(model)
def SetContent(self, model):
self.ui.tv.setModel(model)
i=0
for k,featuretype in features.items():
parent1 = QStandardItem('{}'.format(k[1]))
for item in featuretype:
child = QStandardItem(item[0])
if len(item[1])>0:
for listitem in item[1]:
gchild=QStandardItem(listitem)
child.appendRow(gchild)
parent1.appendRow(child)
model.setItem(i,0,parent1)
self.ui.tv.setFirstColumnSpanned(i,self.ui.tv.rootIndex(),True)
i+=1
这仅适用于硬键控值,例如:
features = {('POLYGON', 'SLPR'): [('ONE WAY', ['NO', 'YES','maybe'], 'List', 3), ('CLASS', ['INTERSTATE', 'PRIMARY', 'RESIDENTIAL', 'SECONDARY', 'SERVICE', 'STATE HWY', 'TERTIARY', 'TRACK', 'US HWY'], 'List', 11)]
但它不适用于我从 csv 或数据框创建的字典 objects,并且出现“字符串索引超出范围错误”。
我也找到了这段代码,这太棒了。但它只给了我重复项和 parents。
reader = csv.reader(f)
for row in reader:
item = QTreeWidgetItem(self.ui.tv, row)
print(row)
下面是一个演示脚本,它应该可以完成您要求的大部分工作。它不能完全产生与第二个屏幕截图相同的布局,但结构是相同的。 csv 文件转换为嵌套 dicts/lists,可以保存到 json 文件。也可以直接加载 json 文件。我假设您的 csv 文件如下所示:
"Test Category","Sub Category","Test Type","Scale Type"
"Premorbid Func.","SIMPLE","Actual","Scale"
"Premorbid Func.","SIMPLE","Predicted","Scale"
"Premorbid Func.","COMPL Montanist","TEST","Scale"
"Premorbid Func.","COMPL Montanist","Actual","Scale"
"Premorbid Func.","COMPL Montanist","Predicted","Scale"
"Intellect","WAIS-IV","WAIS-IV","T Score"
"Intellect","WAIS-IV","VCI","T Score"
"Intellect","WAIS-IV","Similarities","T Score"
"Intellect","WAIS-IV","Vocabulary","T Score"
"Attention","TOVA","RT","Scale"
"Attention","TOVA","RTV","Scale"
"Attention","DV","T","T Score"
树视图如下所示:
演示脚本:
import sys, os, csv, json
from collections import defaultdict
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.buttonLoad = QtWidgets.QPushButton('Load Data')
self.buttonLoad.clicked.connect(self.handleProcessData)
self.buttonSave = QtWidgets.QPushButton('Save Data')
self.buttonSave.clicked.connect(self.handleSaveData)
self.buttonSave.setEnabled(False)
self.tree = QtWidgets.QTreeView()
layout = QtWidgets.QGridLayout(self)
layout.addWidget(self.tree, 0, 0, 1, 2)
layout.addWidget(self.buttonLoad, 1, 0)
layout.addWidget(self.buttonSave, 1, 1)
self.data = None
def loadData(self):
path, ok = QtWidgets.QFileDialog.getOpenFileName(
self, 'Open CSV/JSON', '.', filter='Data Files (*.csv *.json)')
if ok:
with open(path) as stream:
if os.path.splitext(path)[1] == '.json':
self.data = json.load(stream)
else:
reader = csv.reader(stream)
# ignore the header
next(reader)
# convert to nested dicts/lists
self.data = defaultdict(lambda: defaultdict(list))
for record in reader:
self.data[record[0]][record[1]].append(record[2:])
def handleProcessData(self):
self.loadData()
if self.data is not None:
model = QtGui.QStandardItemModel(self.tree)
model.setHorizontalHeaderLabels(('Category', 'Type', 'Scale'))
self.tree.setModel(model)
self.tree.setColumnWidth(0, 200)
root = self.tree.rootIndex()
for row, (text, values) in enumerate(self.data.items()):
category = QtGui.QStandardItem(text)
model.appendRow(category)
self.tree.setFirstColumnSpanned(row, root, True)
for row, (text, values) in enumerate(values.items()):
subcategory = QtGui.QStandardItem(text)
for value in values:
subcategory.appendRow([
QtGui.QStandardItem(),
QtGui.QStandardItem(value[0]),
QtGui.QStandardItem(value[1]),
])
category.appendRow(subcategory)
self.tree.setFirstColumnSpanned(
row, category.index(), True)
self.tree.expandAll()
self.buttonSave.setEnabled(True)
def handleSaveData(self):
path, ok = QtWidgets.QFileDialog.getSaveFileName(
self, 'Save JSON', '.', filter='JSON Files (*.json)')
if ok:
with open(path, 'w') as stream:
json.dump(self.data, stream, indent=2)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Test')
window.setGeometry(600, 100, 540, 480)
window.show()
sys.exit(app.exec_())