• Python绘图系统18:导入txt格式数据


    Python绘图系统:

    简单的数据导入

    由于我们设置了两种导入数据的方式,一种简单的,一种复杂的。如果用复杂的,那么就需要设计一个参数对话框,并获取相关参数;如果用简单的,那么只需沿用之前设置的参数就可以了。

    这隐含着一个必选的方案,即设计几个类成员,用于存放这些参数。最好的地方当然是放在initVar函数中

    def initVar(self, mode):
        self.txtPara = {}
        self.binPara = {}
        self.FILES = [('文本文件', 'txt'), ('文本文件', 'csv'),
                    ('二进制文件', 'bin')]
        # ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    由于目前只对文本文件和二进制有兴趣,所以参数列表也只用了两个。

    接下来先设计简单的数据导入函数

    def btnImportSimple(self, evt):
        f = askopenfilename(filetypes=self.FILES)
        self.data = np.genfromtxt(f, **self.txtPara)
        self.showImData()
    
    def showImData(self):
        tmp = self.data.reshape(-1)[:10].astype(str)
        self.imText.set(", ".join(tmp.tolist()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其中showImData可以展示前10个数值,效果如下

    在这里插入图片描述

    genfromtxt的参数

    复杂文本数据的导入,需要一个参数对话框,我们使用的genfromtxt的常用参数大致有下面这些

    genfromtxt(fname,dtype,comments,delimiter,skipd_header,skip_fonter,converters,missing_values,filling_values,usecols,names, autostrip,**kwarg)
    
    • 1

    其中,大部分参数与loadtxt中含义相同,其他参数的含义如下。

    参数类型含义
    fname字符串文件名
    dtype字符串读取后的数据类型
    comments字符串注释标识符,加载时会自动忽略注释标识符后的字符串
    delimiter字符串分割符,为整数时表示元素最大宽度
    skip_header数值跳过文件头部的字符行数
    skip_footer字数值跳过文件尾部字符串行数
    missing_values字符串指定数组中忽略的值
    filling_values字符串指定某个值用于替代忽略值
    autostrip布尔为True时可自动去除变量首尾的空格
    converters字典或函数用以转化数据格式
    usecols数值使用的列号
    encoding字符串编码方式

    据此先设计一个翻译字典,以便于文件对话框使用

    self.TXTLABEL = {
        "comments" : "注释标识",
        "delimiter" : "分割符号",
        "skip_header" : "文首跳过行数",
        "skip_footer" : "文尾舍弃行数",
        "missing_values" : "指定忽略值",
        "filling_values" : "忽略值替代为",
        "autostrip" : "去除首尾空格",
        "usecols" : " 使用的列号",
        "encoding" : "编码方式",
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    为了实现这些功能的顺利输入,可以设计一个字典参数对话框。然后就可以更改高级文本的导入代码了,有关参数对话框,可参考这篇:tkinter自定义参数对话框

    考虑到这里面有一些参数是整型,所以要在得到数据之后对数据类型进行转换

    def btnImportComplex(self, evt):
        f = askopenfilename(filetypes=self.FILES)
        if f.endswith('.txt'):
            self.txtImport(f)
    
    def txtImport(self, fileName):
        dct = {v:"" for v in self.TXTLABEL.values()}
        AskDct(dct)
        for key in dct:
            if dct[key] == "":
                continue
            if key in ["skip_header", "skip_footer", "usecols"]:
                dct[key] = int(dct[key])
            self.txtPara[key] = dct[key]
        self.data = np.genfromtxt(fileName, **self.txtPara)
        self.showImData()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    源代码

    import tkinter as tk
    import tkinter.ttk as ttk
    from tkinter.filedialog import askopenfilename
    
    import numpy as np
    
    # 字典参数对话框
    class AskDct(tk.Tk):
        def __init__(self, dct):
            super().__init__()
            self.title("请输入参数")
            self.dct = dct
            self.initWidgets()
            self.mainloop()
    
        def initWidgets(self):
            self.varDct = {}
            for i,key in enumerate(self.dct):
                self.varDct[key] = tk.StringVar()
                self.varDct[key].set(self.dct[key])
                frm = tk.Frame(self)
                frm.pack(side=tk.TOP)
                ttk.Label(frm, text=key, width=10).pack(side=tk.LEFT, pady=2)
                ttk.Entry(frm, width=20,
                    textvariable=self.varDct[key]).pack(side=tk.LEFT, pady=2)
    
            frm = tk.Frame(self)
            frm.pack(side=tk.TOP)
            ttk.Button(self, text="取消", width=10,
                command=self.btnCancel).pack(side=tk.RIGHT, pady=2)
            ttk.Button(self, text="确定", width=10,
                command=self.btnOK).pack(side=tk.RIGHT, pady=2)
    
        def btnOK(self):
            for key in self.dct:
                self.dct[key] = self.varDct[key].get()
            self.btnCancel()
    
        def btnCancel(self):
            self.destroy()
            self.quit()
    
    
    class AxisFrame(ttk.Frame):
        # widths 是每个控件的宽度
        def __init__(self, master, label, mode, widths, **options):
            super().__init__(master, **options)
            self.pack()
            self.label = label
            self.initVar(mode)
            self.initWidgets(widths)
        
        def initVar(self, mode):
            self.txtPara = {}
            self.binPara = {}
            self.TXTLABEL = {
                "comments" : "注释标识",
                "delimiter" : "分割符号",
                "skip_header" : "文首跳过行数",
                "skip_footer" : "文尾舍弃行数",
                "missing_values" : "指定忽略值",
                "filling_values" : "忽略值替代为",
                "autostrip" : "去除首尾空格",
                "usecols" : " 使用的列号",
                "encoding" : "编码方式",
            }
            self.FILES = [('文本文件', 'txt'), ('文本文件', 'csv'),
                        ('二进制文件', 'bin')]
            self.MODES = ("序列化", "源代码",  "外部导入", "无数据")
            self.mode = tk.StringVar()
            self.srcText = tk.StringVar()
            self.arrText = [tk.StringVar() for _ in range(3)]
            self.imText = tk.StringVar()
            self.setMode(mode)
        
        def initWidgets(self, widths):
            tk.Label(self, text=self.label, width=widths[0]).pack(side=tk.LEFT)
            slct = ttk.Combobox(self, width=widths[1], 
                textvariable=self.mode)
            slct['value'] = self.MODES
            slct.bind('<>', self.slctChanged)
            slct.pack(side=tk.LEFT)
            self.initRes(widths[2])
    
        def initRes(self, width):
            self.srcEntry = tk.Entry(self, width=width-1, 
                textvariable=self.srcText)
            
            # 序列化参数设置
            self.arrFrame = ttk.Frame(self, width=width-5)
            for i, key in enumerate(["起点", "终点", "步长"]):
                tk.Label(self.arrFrame, text=key).grid(row=0, column=i*3)
                tk.Entry(self.arrFrame, width=int(width/6), 
                    textvariable=self.arrText[i]).grid(row=0, column=i*3+1)
            # 导入数据设置
            self.imFrame = ttk.Frame(self, width=width-5)
            tk.Entry(self.imFrame, width=width-6,
                textvariable=self.imText).pack(side=tk.LEFT)
            btn = ttk.Button(self.imFrame, text="📂", width=3)
            btn.pack(side=tk.LEFT, padx=3)
            btn.bind("", self.btnImportSimple)
            btn.bind("", self.btnImportComplex)        
            self.showRes(self.mode.get())
       
        def btnImport(self):
            f = askopenfilename(filetypes=self.FILES)
            self.imText.set(f)
            return f
        
        def btnImportSimple(self, evt):
            f = askopenfilename(filetypes=self.FILES)
            self.data = np.genfromtxt(f, **self.txtPara)
            self.showImData()
    
        def showImData(self):
            tmp = self.data.reshape(-1)[:10].astype(str)
            self.imText.set(", ".join(tmp.tolist()))
    
        def btnImportComplex(self, evt):
            f = askopenfilename(filetypes=self.FILES)
            if f.endswith('.txt'):
                self.txtImport(f)
    
        def txtImport(self, fileName):
            dct = {v:"" for v in self.TXTLABEL.values()}
            AskDct(dct)
            for key in dct:
                if dct[key] == "":
                    continue
                if key in ["skip_header", "skip_footer", "usecols"]:
                    dct[key] = int(dct[key])
                self.txtPara[key] = dct[key]
            self.data = np.genfromtxt(fileName, **self.txtPara)
            self.showImData()
    
    
        def showRes(self, mode):
            resDct = {"源代码":self.srcEntry, "序列化":self.arrFrame,
                      "外部导入": self.imFrame}
            resDct[mode].pack(padx=5, pady=2, side=tk.LEFT, fill=tk.X)
    
        def slctChanged(self, evt):
            self.srcEntry.pack_forget()
            self.arrFrame.pack_forget()
            self.imFrame.pack_forget()
            mode = self.mode.get()
            self.showRes(self.mode.get())
    
        def setMode(self, mode):
            if type(mode) != str:
                mode = self.MODES[mode]
            self.mode.set(mode)
    
        def setData(self, data=None, **txyz):
            if self.mode.get() == "序列化":
                return self.getArray()
            elif self.mode.get() == "外部导入":
                return self.loadData(data)
            else:
                return self.readPython(**txyz)
        
        def readPython(self, t=None, x=None, y=None, z=None):
            self.data = eval(self.srcText.get())
            return self.data
        
        def loadData(self, data):
            if type(data) != type(None):
                self.data = data
            return self.data
    
        def getArray(self):
            vs = [float(t.get()) for t in self.arrText]
            self.data = np.arange(*vs)
            return self.data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
  • 相关阅读:
    本月本周github热度霸榜项目——jeecgboot
    【商分篇】02 数据指标及指标体系,商业分析的起跑线
    using的应用
    【排版教程】使用Latex ACM 双栏会议模板如何添加跨栏的图片
    Java集合框架
    【每日一题】1523. 在区间范围内统计奇数数目,860. 柠檬水找零
    SpringIOC之support模块SimpleThreadScope
    打破传统电商格局,新型社交电商到底有什么优点?
    【服务器数据恢复】EXT3文件系统的RAID5数据恢复案例
    计算机毕业设计Java搬家预约系统(源码+系统+mysql数据库+lw文档)
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/132155528