学习代码:pandas

import random
import sys, string
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import openpyxl
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QGroupBox, QHBoxLayout, QMenu, QDialog, \
    QLabel


class MyWin(QWidget):
    def __init__(self):
        super().__init__()
        self.setUI()

    def setUI(self):
        self.setWindowTitle('Pandas')

        mainLay = QVBoxLayout()

        # 第1章
        Part1_Button = QPushButton('第1章 基础知识')
        Part1_Menu = QMenu()
        Part1_Button.setMenu(Part1_Menu)
        mainLay.addWidget(Part1_Button)
        Creat_Pandas_Series_Action = Part1_Menu.addAction('1.创建Series')
        Creat_Pandas_Series_Action.triggered.connect(self.Creat_Pandas_Series)
        Pandas_Series_Index_Action = Part1_Menu.addAction('2.Series切片和索引')
        Pandas_Series_Index_Action.triggered.connect(self.Pandas_Series_Index)
        Pandas_Series_IndexValue_Action = Part1_Menu.addAction('3.Series之index和value函数')
        Pandas_Series_IndexValue_Action.triggered.connect(self.Pandas_Series_IndexValue)
        Pandas_Read_File_Action = Part1_Menu.addAction('4.读取本地文件')
        Pandas_Read_File_Action.triggered.connect(self.Pandas_Read_File)
        Pandas_Save_Data_Action = Part1_Menu.addAction('5.保存数据')
        Pandas_Save_Data_Action.triggered.connect(self.Pandas_Save_Data)
        Series_Sort_Action = Part1_Menu.addAction('06.Series排序的两种方法')
        Series_Sort_Action.triggered.connect(self.Series_Sort)

        # 第2章
        Part2_Button = QPushButton('第2章 DataFrame')
        Part2_Menu = QMenu()
        Part2_Button.setMenu(Part2_Menu)
        mainLay.addWidget(Part2_Button)
        Pandas_Creat_DataFrame_Action = Part2_Menu.addAction('1.创建DataFrame')
        Pandas_Creat_DataFrame_Action.triggered.connect(self.Pandas_Creat_DataFrame)
        Pandas_Save_DataFrame_Action=Part2_Menu.addAction('1_1保存至本地数据')
        Pandas_Save_DataFrame_Action.triggered.connect(self.Pandas_Save_Data)
        DataFrame_Attribute_Action = Part2_Menu.addAction('2.DataFrame的属性')
        DataFrame_Attribute_Action.triggered.connect(self.DataFrame_Attribute)
        DataFrame_Lookup_Action = Part2_Menu.addAction('3.DataFrame情况查询')
        DataFrame_Lookup_Action.triggered.connect(self.DataFrame_Lookup)
        DataFrame_Get_RowColumn_Action = Part2_Menu.addAction('4.DataFrame获取行或列')
        DataFrame_Get_RowColumn_Action.triggered.connect(self.DataFrame_Get_RowColumn)
        DataFrame_loc_Action = Part2_Menu.addAction('5.DataFrame之loc')
        DataFrame_loc_Action.triggered.connect(self.DataFrame_loc)
        DataFrame_iloc_Action = Part2_Menu.addAction('6.DataFrame之iloc')
        DataFrame_iloc_Action.triggered.connect(self.DataFrame_iloc)
        DataFrame_getPotData=Part2_Menu.addAction('补01.获取单点数据')
        DataFrame_getPotData.triggered.connect(self.getPotData)
        DataFrame_Exchange_Data_Action = Part2_Menu.addAction('7.DataFrame更改数据')
        DataFrame_Exchange_Data_Action.triggered.connect(self.DataFrame_Exchange_Data)
        DataFrame_Bool_Index_Action = Part2_Menu.addAction('8.DataFrame之布尔索引')
        DataFrame_Bool_Index_Action.triggered.connect(self.DataFrame_Bool_Index)
        Pandas_Str_Function_Action = Part2_Menu.addAction('9.Pandas字符串操作方法(待加强)')
        Pandas_Str_Function_Action.triggered.connect(self.Pandas_Str_Function)
        DataFrame_Missing_Data_Action = Part2_Menu.addAction('10.缺失数据的处理')
        DataFrame_Missing_Data_Action.triggered.connect(self.DataFrame_Missing_Data)

        # 第3章
        Part3_Button = QPushButton('第3章 pandas统计方法')
        Part3_Menu = QMenu()
        Part3_Button.setMenu(Part3_Menu)
        mainLay.addWidget(Part3_Button)
        DataFrame_Statistics_Function_Action = Part3_Menu.addAction('1.pandas常用统计方法')
        DataFrame_Statistics_Function_Action.triggered.connect(self.DataFrame_Statistics_Function)

        # 第4章
        Part4_Button = QPushButton('第4章 合并数据')
        Part4_Menu = QMenu()
        Part4_Button.setMenu(Part4_Menu)
        mainLay.addWidget(Part4_Button)
        Pandas_Data_Join_Action = Part4_Menu.addAction('1.jion按行合并数据')
        Pandas_Data_Join_Action.triggered.connect(self.Pandas_Data_Join)
        Teacher_Pandas_Data_Join_Action = Part4_Menu.addAction('1-1.jion按行合并数据(老师)')
        Teacher_Pandas_Data_Join_Action.triggered.connect(self.Teacher_Pandas_Data_Join)
        Teacher_Join_Action = Part4_Menu.addAction('T01.join')
        Teacher_Join_Action.triggered.connect(self.Teacher_Join)
        Teacher_Merge_Action = Part4_Menu.addAction('T01.merge')
        Teacher_Merge_Action.triggered.connect(self.Teacher_Merge)
        Pandas_Data_Merge_Action = Part4_Menu.addAction('2.merge按列合并数据')
        Pandas_Data_Merge_Action.triggered.connect(self.Pandas_Data_Merge)
        Test_Merge_Action = Part4_Menu.addAction('T01.测试merge')
        Test_Merge_Action.triggered.connect(self.Test_Merge)
        DataFrame_Group_Action = Part4_Menu.addAction('3.分组聚合')
        DataFrame_Group_Action.triggered.connect(self.DataFrame_Group)
        DataFrame_Group_Other_Teacher_Action = Part4_Menu.addAction('3-1分组聚合(其他老师)')
        DataFrame_Group_Other_Teacher_Action.triggered.connect(self.DataFrame_Group_Other_Teacher)
        Recombination_Index_Action = Part4_Menu.addAction('4.复合索引')
        Recombination_Index_Action.triggered.connect(self.Recombination_Index)
        DataFrame_Data_Concat_Action = Part4_Menu.addAction('11.竖向合并concat')
        DataFrame_Data_Concat_Action.triggered.connect(self.DataFrame_Data_Concat)

        # 第5章
        Part5_Button = QPushButton('第5章 时间序列')
        Part5_Menu = QMenu()
        Part5_Button.setMenu(Part5_Menu)
        mainLay.addWidget(Part5_Button)
        DataFrame_Date_Range_Action = Part5_Menu.addAction('1.时间序列')
        DataFrame_Date_Range_Action.triggered.connect(self.DataFrame_Date_Range)

        # 第6章
        Part6_Button = QPushButton('第6章 分组聚合与索引')
        Part6_Menu = QMenu()
        Func_groupby_Action = Part6_Menu.addAction('01.groupby函数')
        Func_groupby_Action.triggered.connect(self.Func_groupby)
        set_index_Action = Part6_Menu.addAction('02.复合索引set_index')
        set_index_Action.triggered.connect(self.set_index)
        reset_index_Action = Part6_Menu.addAction('03.reset_index')
        reset_index_Action.triggered.connect(self.reset_index)
        Index_Reindex_Set_index_Action = Part6_Menu.addAction('04.重置索引reindex')
        Index_Reindex_Set_index_Action.triggered.connect(self.reindex)
        index_columns_Action = Part6_Menu.addAction('05.index_columns')
        index_columns_Action.triggered.connect(self.index_columns)

        Part6_Button.setMenu(Part6_Menu)
        mainLay.addWidget(Part6_Button)

        # 第7章
        Part7_Button = QPushButton('第7章 进阶知识')

        Part7_Menu = QMenu()

        Quantile_Action = Part7_Menu.addAction('01.统计_分位数函数')
        Quantile_Action.triggered.connect(self.Quantile_Function)
        Aplly_Action = Part7_Menu.addAction('02.apply函数')
        Aplly_Action.triggered.connect(self.Func_apply)
        Add_columns_Action = Part7_Menu.addAction('03.DataFrame增加列')
        Add_columns_Action.triggered.connect(self.Add_columns)
        Series_Calculate_Action = Part7_Menu.addAction('04.Series的运算')
        Series_Calculate_Action.triggered.connect(self.Series_Calculate)
        AdjustColumns_Action = Part7_Menu.addAction('05.调整DataFrame列顺序')
        AdjustColumns_Action.triggered.connect(self.AdjustColumns)
        Data_Cleaning_Action = Part7_Menu.addAction('06.数据清洗三剑客')
        Data_Cleaning_Action.triggered.connect(self.Data_Cleaning)
        ManySeriesToDataFrame = Part7_Menu.addAction('07.多个Series合并为DataFrame')
        ManySeriesToDataFrame.triggered.connect(self.ManySeriesToDataFrame)
        DataFrameSort_Action = Part7_Menu.addAction('08.DataFrame排序')
        DataFrameSort_Action.triggered.connect(self.DataFrameSort)

        Part7_Button.setMenu(Part7_Menu)
        mainLay.addWidget(Part7_Button)

        self.setLayout(mainLay)

    def Creat_Pandas_Series(self):  # 1.创建Series

        # 1.通过列表,range值,元组或numpy中一维数组创建Series
        print('-' * 10 + '1.通过列表,range值,元组或numpy中一维数组创建Series')
        t1 = pd.Series(data=["P", "Q", "K", "L"], index=list('ABCD'), dtype='str')
        print(t1)
        print(type(t1))
        t2 = pd.Series(data=range(16, 20), index=list('EFGH'), dtype='int8')
        print(t2)
        print(type(t2))
        t3 = pd.Series(data=(1, 2, 3, 4), index=list('EFGH'), dtype='int8')
        print(t3)
        print(type(t3))
        t4 = pd.Series(data=np.arange(96, 100), index=list('EFGH'), dtype='int8')
        print(t4)
        print(type(t4))
        '''
        修建Series的语法
            1.pd.Series(),data参数传入的数据可以为列表,range值,元组,或numpy中一维数组,但是集合不可以,
              index是索引值,传入数据类型是列表,dtype参数用来指定数据类型
            2.pd.Series的输出结果左侧为索引值,右侧为数据
        '''
        # 2.通过字典创建Series
        print('-' * 10 + '2.通过字典创建Series')
        dict1 = {'A': 1, 'B': 2, 'C': 3, 'D': 4, }
        t5 = pd.Series(dict1)
        print(t5)
        print(type(t5))
        '''
        通过字典创建一个Series,默认的索引就是字典的键
        '''
        # 3.创建字典创建Series,如果重新给定义索引,能对应上则取字典对应键的值,否则为NaN
        print('-' * 10 + '3.创建字典创建Series,如果重新给定义索引,能对应上则取字典对应键的值,否则为NaN')
        a = {string.ascii_uppercase[i]: i for i in range(10)}
        print(a)
        print(type(a))
        t6 = pd.Series(a, index=list(string.ascii_uppercase[5:15]))
        print(t6)
        '''
            1.numpy中nan为float,pandas会自动根据数据类更改series的dtype类型
            2.string.ascii_uppercase的作用:将26个字母的序号转化的大写英文字母

        '''
        # 4.pd.Series修改数据类型的方法同numpy
        print('-' * 10 + '4.pd.Series修改数据类型的方法同numpy')
        t7 = pd.Series(range(6), index=list('ABCDEF'))
        print(t7)
        t8 = t7.astype(float)
        print(t8)

    def Pandas_Series_Index(self):  # 2.Series切片和索引
        a = {string.ascii_uppercase[i]: i for i in range(10)}
        t1 = pd.Series(a)
        print(t1)
        # 1.使用序号索引
        print('1.使用序号索引'.center(60, '-'))
        print(t1[1])  # 索引单个值
        print(t1[2:6])  # 索引一个区间
        print(t1[2:10:2])  # 索引带步长的区间
        print(t1[[2, 6, 7]])  # 索引不连续的数值,切记传入参数为一个列表
        # 2.使用索引值进行索引
        print('2.使用索引值进行索引'.center(60, '-'))
        x=t1['A']
        print(x)  # 索引单个值
        print(f'单个值的数据类型:{type(x)}')
        print(t1[["A", 'D', 'F']])  # 索引不连续的数值,切记传入参数为一个列表
        # 3.使用布尔索引
        print('3.使用布尔索引'.center(60, '-'))
        print(t1[t1 > 5])

    def Pandas_Series_IndexValue(self):  # 3.Series之index和value函数
        a = {string.ascii_uppercase[i]: i for i in range(10)}
        t1 = pd.Series(a)
        print(t1)
        print(t1.index)
        print(t1.values)
        '''
        t1.index和t1.value均为可遍历对象
        '''

    def Pandas_Read_File(self):  # 4.读取本地文件
        # 1.读取csv文件
        t1 = pd.read_csv('学生成绩.csv')
        print(t1)
        # 2.读取excel文件
        t2 = pd.read_excel('学生成绩.xlsx')
        print(t2)
        t3 = pd.DataFrame(np.arange(12).reshape(3, 4), index=['白', '良', '贺'], columns=['努', '力', '拼', '搏'])
        print('-' * 29)
        print(t3)

    def Pandas_Save_Data(self):  # '5.保存数据

        list1 = [{'姓名': "张三", '年龄': 18, '电话': 10001}, {'姓名': "李四", '年龄': 22, '电话': 10086},
                 {'姓名': "王五", '年龄': 29, '电话': 10010}, {'姓名': "赵六", '年龄': 27}]
        t2 = pd.DataFrame(list1)
        print(t2)
        # 1.保存为csv文件
        t2.to_csv('员工信息.csv', encoding='utf_8_sig')
        # 2.保存为excel文件
        t2.to_excel('员工信息.xlsx', encoding='utf_8_sig')
        # 3.保存文件时不保存行列索引
        t2.to_csv('员工信息(不保存行列索引).csv', index=False, header=False)

    def Series_Sort(self):
        '''
            资料来源:https://www.py.cn/jishu/jichu/23572.html
        '''
        obj = pd.Series([1, 3, 2, 5, 6], index=list('dabce'))
        print(obj)
        # 1.series使用sort_index方法通过索引进行排序
        obj.sort_index(ascending=True, inplace=True)
        print(obj)
        # 2.series使用sort_values方法通过值进行排序
        obj.sort_values(ascending=False, inplace=True)
        print(obj)
        '''
        参数含义:
        axis
            指定轴,可选行轴和列轴,0 代表根据行索引排序,1 表示通过列排序,默认如上函数为 0。
        level
            指定索引级别,若设置,则按照指定的级别排序,默认为 None,即以索引的值进行排序。
        ascending
            是否升序排序,默认是 True,即升序排序。
        inplace
            是否改变原对象的实际排序,默认是 False,即不改变原对象的状态。
        kind
            指定排序的算法,可选项为 {'quicksort', 'mergesort', 'heapsort'},默认为 'quicksort' 即使用快排方式。
        na_position
            空值(NaN)应该排序的位置,可选项有 {'first', 'last'},默认为 'last',即放在最后面。
        sort_remaining
            如果为 True,且按级别和索引排序是多层,反之按指定级别排序后也按其他级别(按顺序)排序。
        ignore_index
            是否忽略 DataFrame 对象的索引值,默认为 False;1.0.0 版本开始新增的参数。
        '''

    def Pandas_Creat_DataFrame(self):  # 1.创建DataFrame
        # 1.通过数组方法创建DataFrame
        t1 = pd.DataFrame(np.arange(12).reshape(3, 4), index=['白', '良', '贺'], columns=['努', '力', '拼', '搏'])
        print('-' * 29)
        print(t1)
        # 2.通过列表中嵌套字典的方法创建DataFrame
        list1 = [{'姓名': "张三", '年龄': 18, '电话': 10001}, {'姓名': "李四", '年龄': 22, '电话': 10086},
                 {'姓名': "王五", '年龄': 29, '电话': 10010}, {'姓名': "赵六", '年龄': 27}]
        t2 = pd.DataFrame(list1)
        print(t2)
        # 3.通过字典嵌套列表方式创建DataFrame
        dict1 = {'c1': list('ABCD'),
                 'c2': list('EFGH'),
                 'C3': list('IJKL')
                 }
        df = pd.DataFrame(dict1)
        print(df)
        '''
        1.pd.DataFrame()方法,传入的数据可以是numpy二维数组,也可以是字典
        2.DataFrame对象既有行索引,又有列索引
            行索引,表明不同行,横向索引,叫index,0轴,axis=O
            列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
        3.缺少的值会显示为NaN
        4.可以使用汉字作为行索引和列索引
        '''
    def DataFrame_Save(self):
        list1 = [{'姓名': "张三", '年龄': 18, '电话': 10001}, {'姓名': "李四", '年龄': 22, '电话': 10086},
                 {'姓名': "王五", '年龄': 29, '电话': 10010}, {'姓名': "赵六", '年龄': 27}]
        t2 = pd.DataFrame(list1)
        print(t2)
        print(t2)
    def DataFrame_Attribute(self):  # 2.DataFrame的属性
        t1 = pd.read_csv('学生成绩.csv')
        print(t1)
        # 1.行数、列数
        print(t1.shape)
        # 2.数据类型
        print(t1.dtypes)
        # 3.数据维度
        print(t1.ndim)
        # 4.行索引
        print(t1.index)
        # 5.列索引
        print(t1.columns)
        # 5.对象二值,二维数组
        print(t1.values)

    def DataFrame_Lookup(self):  # 3.DataFrame情况查询
        t1 = pd.read_csv('学生成绩.csv')
        print(t1)
        # 1.查询头部几行,默认是5行
        print('-' * 10 + '1.查询头部几行,默认是5行')
        print(t1.head(2))
        # 2.查询尾部几行,默认是5行
        print('-' * 10 + '2.查询尾部几行,默认是5行')
        print(t1.tail(2))
        # 3.查询信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用
        print('-' * 10 + '3.查询信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用')
        print(t1.info())
        # 4.快速综合统计结果︰计数,均值,标准差,最大值,四分位数,最小值
        print('-' * 10 + '4.快速综合统计结果︰计数,均值,标准差,最大值,四分位数,最小值')
        print(t1.describe())

    def DataFrame_Get_RowColumn(self):  # 4.DataFrame获取行或列
        t1 = pd.DataFrame(np.arange(35).reshape(5, 7), index=['白', '良', '贺', '加', '油'],
                          columns=['A', 'B', 'C', 'D', 'E', 'F', 'G'])
        print(t1)
        # 1.获取连连续行(不适用获取单个行或不连续的行)
        print(t1[:3])  # 获取区间[0:)中的行
        print(t1[2:])  # 获取第2行及其以后的所有行
        print(t1[1:4])  # 获取区间[1:4)中的行
        print(t1['白':'贺'])  # 采用行索引标识可以获取连续行,道理同数字行号区间
        # 2.获取单列:通过输入列索引的方式获取单列,但是不支持获取多列
        print(t1['A'])
        # 3.获取第4列的前3个数据
        print(t1[:3]['D'])

    def DataFrame_loc(self):  # 5.DataFrame之loc
        t1 = pd.DataFrame(np.arange(56).reshape(7, 8), index=list('ABCDEFG'), columns=list('STUVWXYZ'))
        print(t1)
        # 1.获取行
        print('-' * 10 + '1.获取行')
        print(t1.loc[["A"], :])  # 获取单行
        print(t1.loc[["A", 'D'], :])  # 获取不连续多行
        print(t1.loc["A":'D', :])  # 获取连续多行
        # 2.获取列
        print('-' * 10 + '2.获取列')
        print(t1.loc[:, ['T']])

        print(t1.loc[:, ['T', 'X']])
        print(t1.loc[:, 'T':'X'])
        # 3.获取单元个点或区域
        print('-' * 10 + '3.获取单元个点或区域')
        print(t1.loc[['A'], ['T']])  # 获取单个坐标点
        print(t1.loc[['A', 'D'], ['T', 'X']])  # 获取不连续坐标轴的交点数据,这一点同numpy中写法不同
        print(t1.loc['A':'D', 'T':'X'])  # 获取连续区间数据
        print(t1.loc[['A'], 'T':'X'])  # 非连续行列号同连续行列号混写
        # 4.无行索引之loc(试验后可用)
        print('-' * 10 + '4.无行索引之loc')
        t2 = pd.DataFrame(np.arange(56).reshape(7, 8), columns=list('STUVWXYZ'))
        print(t2)
        print(t2.loc[[0], ['T']])  # 获取单个坐标点
        print(t2.loc[[0, 3], ['T', 'X']])  # 获取不连续坐标轴的交点数据,这一点同numpy中写法不同
        print(t2.loc[0:0, 'T':'X'])  # 获取连续区间数据
        print(t2.loc[[0], 'T':'X'])  # 非连续行列号同连续行列号混写
        print(t2.loc[[0], ['T', 'X']])
        list1 = ['T', 'X']
        print(t2.loc[[0], list1])
        print(t2.loc[0, list1])
        a = 0
        print('-' * 19 + '传参')
        print(t2.loc[a, list1])
        print(t2.loc[[a], list1])
        # 5.t1.loc[:, 'T']和t1.loc[:, ['T']]数据类型的区别
        print('-' * 10 + "t1.loc[:, 'T']和t1.loc[:, ['T']]数据类型的区别")
        print(type(t1.loc[:, 'T']))
        print(type(t1.loc[:, ['T']]))

        # -----------知识总结------------
        '''
        1.t1.loc[]函数后面是中括号,不是小括号
        2.获取数据的格式:ti.loc[:,:]
            a.中括号里面的逗号前面用中括号书写行标,逗号后面用中括号书写列标
            b.获取连续多行或多列时,","前或后连续多行或多列的标记采用类似'T':'X'方式书写,若中括号中采用此方法书写会报错.
            c.即单个行列号不连续行列号书写方式不一致,而连续行列号书写方式不一致.  
            d.本书写格式优于老师讲课的书写格式,方便记忆使用而不至于混乱. 
            e.行索引可以为数字,索引可以为字符串,loc方法同样可以使用,此时仅需要将索引改为数字序号即可     
        3.t1.loc[:,'T']数据类型是pandas.core.series.Series,而t1.loc[:,['T']]的数据类型则是DataFrame。  
        '''

    def DataFrame_iloc(self):  # 6.DataFrame之iloc
        t1 = pd.DataFrame(np.arange(56).reshape(7, 8), index=list('ABCDEFG'), columns=list('STUVWXYZ'))
        print(t1)
        # 1.获取行
        print('-' * 10 + '1.获取行')
        print(t1.iloc[[0], :])  # 获取单行
        print(t1.iloc[[0, 3], :])  # 获取不连续多行
        print(t1.iloc[0:3, :])  # 获取连续多行
        # # 2.获取列
        print('-' * 10 + '2.获取列')
        print(t1.iloc[:, [1]])
        print(t1.iloc[:, [1, 5]])
        print(t1.iloc[:, 1:5])
        # 3.获取单元个点或区域
        print('-' * 10 + '3.获取单元个点或区域')
        print(t1.iloc[[0], [1]])  # 获取单个坐标点
        print('单个点的数据类型:',type(t1.iloc[[0], [1]]))
        print(t1.iloc[[0, 3], [1, 5]])  # 获取不连续坐标轴的交点数据,这一点同numpy中写法不同
        print(t1.iloc[0:3, 1:5])  # 获取连续区间数据
        print(t1.iloc[[0], 1:5])  # 非连续行列号同连续行列号混写
        # -----------知识总结------------
        '''
        t1.loc和t1.iloc的区别在于前者传入的是列行的索引号,而后者传入的是行列的数字序号,但是二者的使用方法一致.
        '''
    def getPotData(self):
        print('单点')

        # 创建一个简单的DataFrame
        df = pd.DataFrame({
            'A': ['A', 2, 3],
            'B': ['B', 5, 6],
            'C': ['C', 8, 9]
        })
        print(df)

        # 使用.at获取指定行列的数据
        value_label = df.at[0, 'A']  # 获取第一行"A"列的数据
        print(value_label,type(value_label))  # 输出: 1

        value_index = df.at[2, 'C']  # 获取第三行"C"列的数据
        print(value_index)  # 输出: 9

        # 使用.iat获取指定行列的数据(假设你知道行列的索引数字)
        value_iat_1 = df.iat[0, 0]  # 获取第一行第一列的数据
        print(value_iat_1)  # 输出: A

        value_iat_2 = df.iat[2, 2]  # 获取第三行第三列的数据
        print(value_iat_2)  # 输出: 9
        pass
    def DataFrame_Exchange_Data(self):  # 7.DataFrame更改数据
        t1 = pd.DataFrame(np.arange(56).reshape(7, 8), index=list('ABCDEFG'), columns=list('STUVWXYZ'))
        print(t1)

        # 1.将数据更改为具体的数据
        print('-' * 10 + '1.将数据更改为具体的数据')
        t1.iloc[1:4, 5:7] = 250
        print(t1)

        # 2.将数据更改为NaN
        print('-' * 10 + '2.将数据更改为NaN')
        t1.iloc[1:4, 5:7] = np.nan
        print(t1)
        # 3.将数据更改为inf
        print('-' * 10 + '3.将数据更改为inf')
        t1.iloc[1:4, 5:7] = np.inf
        print(t1)
        # 4.将更改单个数据
        print('-' * 10 + '4.将更改单个数据')
        t1.iloc[1,1]=888888
        print(type(t1.iloc[1,1]))
        print(t1)
        # -----------知识总结------------
        '''
            1.索引至DataFrame的具体位置的数据,并对其重新赋值,再次输出该DataFrame,赋值位置的数据即为修改后的数据
            2.将数据赋值赋值为nan或inf,对应列位置的数据类型均变为float类型
        '''

    def DataFrame_Bool_Index(self):  # 8.DataFrame之布尔索引
        print('课堂练习'.center(59, '-'))
        t1 = pd.DataFrame(np.arange(56).reshape(7, 8), index=list('ABCDEFG'), columns=list('STUVWXYZ'))
        print(t1)
        # 1.bool条件的输出结果
        print(t1['X'] > 30)
        # 2.单个布尔索引条件
        print(t1[t1['X'] > 30])  # t1[t1['X']>30]表示t1中X列中所有大于30的数据所在的行
        # 3.多个布尔条件
        print(t1[(t1['Z'] > 25) & (t1['Z'] < 40)])
        print(t1[(t1['Z'] < 25) | (t1['Z'] > 40)])
        # 4.布尔索引实战
        print('布尔索引实战'.center(59, '-'))
        df = pd.read_csv('交易日20230602收盘价分位数(更新日期2023-06-05).csv')
        print(df)
        bool = df[(df['position'] == 'Q30') | (df['position'] == 'Q20') | (df['position'] == 'Q10')]
        print(bool)

        def My_V_Func(data, col, mylist: list):
            # mylist=['Q30','Q20','Q10']
            # print(mylist)
            print('My_V_Func'.center(59, '-'))
            # data=df
            # bool=data[(data[col]==mylist[0]) | (data[col]==mylist[1]) | (data[col]==mylist[2])]
            fuhao = '|'
            bool = data[(data[col] == mylist[0]) | (data[col] == mylist[1]) | (data[col] == mylist[2])]
            mydf = bool.sort_values(by=['ts_code'], ascending=True, inplace=False)
            mydf.index = [i for i in range(mydf['ts_code'].count())]
            print(mydf)

            # bool.to_csv('布尔索引函数1.csv',encoding='utf_8_sig')

        My_V_Func(data=df, col='position', mylist=['Q30', 'Q20', 'Q10'])
        # 5.多个条件关于'|'符号的布尔索引函数
        print("5.多个条件关于'|'符号的布尔索引函数".center(59, '-'))

        def V_Func(data, col, mylist: list):  # 可以参考此函数写一个关于'&'符的多条件布尔索引
            # print('V_Func'.center(59,'-'))

            result = pd.DataFrame()
            for i in mylist:
                bool = data[data[col] == i]
                result = pd.concat([result, bool])
            #         mydaily2 = pd.concat([mydaily2, mydf]).reset_index(drop=True)

            mydf = result.sort_values(by=['ts_code'], ascending=True, inplace=False)
            num = result['ts_code'].count()
            mydf.index = [i for i in range(num)]
            print(mydf)
            # result.to_csv('布尔索引函数2.csv',encoding='utf_8_sig')

        V_Func(data=df, col='position', mylist=['Q30', 'Q20', 'Q10', 'Q05'])
        # -----------知识总结------------
        '''
            1.'&'和'|'分别是and和or的含义,即并和或的含义
            2.使用'&'和'|'两个符号,符号两侧的条件要用小括号括起来,否则运行时会出错.
            3.这里的代码不可以使用and和or否则会报错.
        '''

    def Pandas_Str_Function(self):  # 9.Pandas字符串操作方法(待加强)
        filmlist = ['战狼2', '速度与激情8', '功夫瑜伽', '西游伏魔篇', '变形金刚5:最后的骑士', '摔跤吧!爸爸',
                    '加勒比海盗5:死无对证', '金刚:骷髅岛',
                    '极限特工:终极回归', '生化危机:终章', '乘风破浪', '神偷奶爸3', '智取威虎山', '大闹天竺',
                    '金刚狼3:殊死一战', '蜘蛛侠:英雄归来',
                    '悟空传', '银河护卫队2', '情圣', '新木乃伊']
        sellmoney = [56.01, 26.94, 17.53, 16.49, 15.45, 12.96, 11.8, 11.61, 11.28, 11.12, 10.49, 10.3, 8.75, 7.55, 7.32,
                     6.99, 6.88, 6.86, 6.58, 6.23]
        # 1.将数据写入excel
        xls1 = openpyxl.Workbook()
        sheet1 = xls1.active
        for i in range(len(filmlist)):
            sheet1.cell(row=i + 1, column=1).value = filmlist[i]
            sheet1.cell(row=i + 1, column=2).value = sellmoney[i]
        xls1.save('电影信息(pandas学习用).xlsx')
        # 2.读取excel中的数据
        t1 = pd.read_excel('电影信息(pandas学习用).xlsx')
        t1.columns = ['电影名称', '票房']
        print(t1)
        # 3.字符串操作方法
        print(t1['电影名称'].str.len())  # 获取"电影名称"列各元素的字符串长度
        print(t1['电影名称'].str.get(1))  # 获取"电影名称"列各元素的字符串第一个元素

        # -----------知识总结------------
        '''
            方法                              说明
            cat                             实现元素级的字符串连接操作,可指定分隔符
            contains                        返回表示各字符串是否含有指定模式的布尔型数组
            count                           模式的出现次数
            endswith, startswith            相当于对各个元素执行x.endswith(pattern)或x.startswith(pattern)
            findall                         计算各字符串的模式列表
            get                             获取各元素的第i个字符
            join                            根据指定的分隔符将Series中各元素的字符串连接起来
            len                             计算各字符串的长度
            lower、 upper                    转换大小写。相当于对各个元素执行x.lower()或x.upper0
            match                           根据指定的正则表达式对各个元素执行re.match
            pad                             在字符串的左边、右边或左右两边添加空白符
            center                          相当于pad(side='both')
            repeat                          重复值。例如,s.str.repeat(3)相当于对各个字符串执行x*3
            replace                         用指定字符串替换找到的模式
            slice                           对Series中的各个字符串进行子串截取
            split                           根据分隔符或正则表达式对字符串进行拆分
            strip. rstrip、 lstrip            去除空白符,包括换行符。相当于对各个元素执行x.strip()、x.rstrip0、x.lstripo)

        '''

    def DataFrame_Missing_Data(self):  # 10.缺失数据的处理
        t1 = pd.DataFrame(np.arange(56).reshape(7, 8), index=list('ABCDEFG'), columns=list('STUVWXYZ'))
        t1.iloc[0:3, 5:] = np.nan
        print(t1)
        # 1.判断DataFrame中数据是否为nan
        print(pd.isna(t1))
        print(pd.isnull(t1))
        '''两个方法用途一样'''
        # 2.将nan替换成某个数值
        t2 = t1.fillna(250)
        print(t2)
        '''
        t1.fillna()返回结果是一个DataFrame
        '''
        # 3.删除nan所在的行或列
        t3 = t1.dropna(axis=0)  # 非nan行
        print(t3)
        t4 = t1.dropna(axis=1)  # 非nan列
        print(t4)
        # 4.将为0的数据赋值成nan
        t1[t1 == 0] = np.nan
        print(t1)
        # -----------知识总结------------
        '''
        1.数据缺失出现的两种情况:
            一种就是空,None等,在pandas是NaN(和np.nan一样)
            另一种是我们让其为0,蓝色框中
        2.缺失数据的处理
            对于NaN的数据,在numpy中我们是如何处理的?在pandas中我们处理起来非常容易
            判断数据是否为NaN: pd.isnull(df),pd.notnull(df)
            处理方式1∶删除NaN所在的行列dropna (axis=0, how='any', inplace=False)处理方式2:填充数据,t.fillna(t.mean()),t.fiallna(t.median()),t.fillna(0)
            处理为O的数据:t[t==0]=np.nan
            当然并不是每次为0的数据都需要处理
            计算平均值等情况,nan是不参与计算的,但是0会
        '''

    def DataFrame_Statistics_Function(self):  # 1.pandas常用统计方法
        t1 = pd.read_csv('学生成绩.csv')
        t1.columns = ['语文', '数学', '英语', '物理']
        t1[t1 > 95] = np.nan
        print(t1)
        # 1.最大值
        print(t1['物理'].max())
        # 2.平均值所在的行
        print(t1['物理'].argmax())
        # 3.最小值
        print(t1['物理'].min())
        # 4.最小值所在的行
        print(t1['物理'].argmin())
        # 5.平均值
        print(t1['物理'].mean())
        # 6.中位数
        print(t1['物理'].median())
        # 7.标准差
        print(t1['物理'].std())
        '''
            pandas没有ptp方法
        '''

    def Pandas_Data_Join(self):  # 1.jion按行合并数据
        t1 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list('ABC'), columns=list('VXYZ'))
        print(t1)
        t2 = pd.DataFrame(np.arange(20).reshape(4, 5), index=list('CFHB'))
        print(t2)

        print(t1.join(t2))
        print(t2.join(t1))
        '''
        规律:
            合并时,所有的行数以前面的数据为准,后面数据中没有的行,合并时,以nan填充
        '''

    def Teacher_Pandas_Data_Join(self):  # 1-1.jion按行合并数据(老师)
        df = pd.read_csv('film_data.csv')
        list1 = df['Sort'].str.split(',').tolist()
        list2 = [list(set(list1[i])) for i in range(len(list1))]
        '''
            每个电影Sort分类有重复的,故需要对list1进行去重操作,操作程序运行会报错。
        '''
        set1 = set(j for i in list2 for j in i)
        list3 = list(set1)
        # 构造全为零数组
        t1 = pd.DataFrame(np.zeros((df.shape[0], len(list3))), columns=list3)
        for i in range(t1.shape[0]):
            t1.loc[i, list2[i]] = 1
        sort_sum = t1.sum(axis=0)
        print(sort_sum)
        print(type(sort_sum))
        sort_ord = sort_sum.sort_values()
        print(sort_ord)
        # 绘图
        plt.figure(figsize=(20, 12), dpi=80)
        plt.bar(sort_ord.index, sort_ord.values)
        plt.show()

    def Teacher_Join(self):  # T01.join
        t1 = pd.DataFrame(np.ones((3, 4)), index=list('ABC'), columns=list('KLMN'))
        t2 = pd.DataFrame(np.zeros((2, 5)), index=list('AB'), columns=list('VWXYZ'))
        print(t1)

        print(t2)
        print(t1.join(t2))
        print(t2.join(t1))

    def Teacher_Merge(self):  # T01.merge
        t1 = pd.DataFrame(np.ones((3, 4)), index=list('ABC'), columns=list('KLMN'))
        t2 = pd.DataFrame(np.zeros((2, 5)), index=list('AB'), columns=list('VWXYZ'))
        t3 = pd.DataFrame(np.arange(9).reshape(3, 3), columns=list('fKx'))
        print(t1)
        print(t2)
        print(t3)
        # 1.空DataFrame
        print(t1.merge(t3, on="K"))
        t3.loc[1, "K"] = 1
        # 2.将t3第1行和K列交点数据赋值为1
        print(t1.merge(t3, on="K"))
        '''
        10分钟之后认真听
        老师讲的参数:on,how,left_on,right_on
        注意理解并集的含义:即相同列在t1中有两个,t3中只有一个1,注意观察其合并效果
        inner交集,outer并集,老师原来的课件是错误的,临近下课时老师又修正回来了
        '''

    def Pandas_Data_Merge(self):  # 2.merge按列合并数据
        # 1.左右两侧有相同的列名
        print('-' * 10 + '1.左右两侧有相同的列名')
        left1 = pd.DataFrame({"name": ['张三', '李四', '赵五'], "age": [18, 20, 19], 'tel': [10000, 10010, 10086]})
        print(left1)
        right1 = pd.DataFrame({"name": ['王五', '刘七', '朱八'], "age": [80, 70, 90]})
        print(right1)
        print(pd.concat([left1, right1], axis=0, join='outer'))
        # 2.左右两侧没有共同的列名
        print('-' * 10 + '2.左右两侧没有共同的列名')
        left2 = pd.DataFrame({"name": ['张三', '李四', '赵五'], "age": [18, 20, 19]})
        print(left2)
        right2 = pd.DataFrame({"姓名": ['张三', '李四', '王六'], "grade": [80, 70, 90]})
        print(right2)
        print(left2.merge(right2, left_on='name', right_on='姓名'))

    def Test_Merge(self):  # T01.测试merge
        '''merge:按照指定的列把数据按照一定方式合并到一起'''
        t1 = pd.DataFrame(np.ones((3, 4)), index=list('ABC'), columns=list('KLMN'))
        t1.loc[["B"], ["L"]] = 2
        t2 = pd.DataFrame(np.arange(9).reshape(3, 3), columns=list('fLx'))
        print(t1)
        print(t2)
        # 1.默认内连接inner即交集
        print(t1.merge(t2, on="L"))
        # 2.内连接inner即交集
        print('-' * 10 + '内连接inner')
        print(t1.merge(t2, on="L", how='inner'))
        '''
            1.t1的L列同t2的L列中的值相同的值有2个,所以显示两行。同理如果相同只有一行,则显示一行
            2.会将右侧t2对应的值加上共同列上,待总结。此叙述明显不通顺。
        '''
        # 3.外连接outer即并集
        print('-' * 10 + '外连接outer')
        print(t1.merge(t2, on="L", how='outer'))
        '''
            1.外连接的行数等于t1和t2的L列中共同的数值个数2加不同的数值个数3,共5个
            2.最上面的行显示交集行,t1不同行,最后显示t1中不存在的行
            3.K列中并集数据,如果在t1中不存在,则产生的新行在原t1位置用nan补充;K列中并集数据,如果在t2不存在,则产生的新行在原2位置用nan补充
            4.只要是t1和t2原有的数值都可以正常显示,否则用nan补充,此描述是否完善待总结
            5.从图中发规律,左边部分为t1中的列名称,右边为t2中扣除有共同数据的列之后的列名称.

        '''
        # 4.左连接left
        print('-' * 10 + '左连接left')
        print(t1.merge(t2, on="L", how='left'))
        # 5.右连接right
        print('-' * 10 + '右连接right')
        print(t1.merge(t2, on="L", how='right'))
        '''
            1.右连接的行数等于t1和t2的L列中共同的数值个数2加t2中不同的数值个数2,共4个
            2.最上面的行显示交集行,下面t2不同行
            3.K列中右连接数据,如果在t1中不存在,则产生的新行在原t1位置用nan补充
        '''
        # 示例1
        print('-' * 10 + '示例1')
        dict1 = {'学号': [0, 1, 2, 3, 4, 5, 6, 7, 8],
                 '姓名': ['小明', '小刚', '小红', '小兰', '李华', '张三', '李四', '王五', '小张'],
                 '成绩': [90, 89, 98, 63, 95, 23, 56, 85, 72],
                 '学校': ['一中', '三中', '附中', '二中', '一中', '一中', '附中', '二中', '附中']}
        left = pd.DataFrame(dict1)
        print(left)
        dict2 = {'学号': [0, 1, 2, 9], '年级': ['三年级', '五年级', '六年级', '六年级'],
                 '班级': ['二班', '三班', '一班', '一班']}
        right = pd.DataFrame(dict2)
        print(right)
        print('测试')
        print(left.merge(right, on='学号'))
        # 示例2
        print('-' * 10 + '示例2')
        info1 = {'学号': [0, 1, 2, 3, 4, 5, 6, 7, 8],
                 '姓名': ['小明', '小刚', '小红', '小兰', '李华', '张三', '李四', '王五', '小张'],
                 '成绩': [90, 89, 98, 63, 95, 23, 56, 85, 72],
                 '学校': ['一中', '三中', '附中', '二中', '一中', '一中', '附中', '二中', '附中']}

        info2 = {'校长': ['白良贺', '肖灿', '肖卜赫', '肖淑秀'], '学校': ['一中', '二中', '三中', '四中'],
                 '地址': ['北京海淀', '河南二七区', '上海东方明珠', '广东白云']}
        inf1 = pd.DataFrame(info1)
        inf2 = pd.DataFrame(info2)
        print(inf1)
        print(inf2)
        print(inf1.merge(inf2, on='学校'))
        '''
        关于merge的学习资料《关于merge函数的总结【待完善】》:
            腾讯微动:https://share.weiyun.com/g6vuS2U4
            阿里云盘:https://www.aliyundrive.com/s/uEAsxJCPjN5
        '''

    def DataFrame_Group(self):  # 3.分组聚合
        t1 = pd.read_csv('student_info.csv', encoding='gbk')
        # print(t1)
        t2 = t1.groupby(by='省份')
        print(t2.get_group('河南'))
        # print(t2.count())
        # print(type(t2))

        # for i,j in t2:
        #     print(i)
        #     print(type(i))
        #     print(j)
        #     print(type(j))
        henan_count = t2['姓名'].count()
        print(henan_count)
        print('年龄'.center(60,'-'))
        age_max=t2['年龄'].max()
        age_min=t2['年龄'].min()
        age_mean=t2['年龄'].mean()
        max=float(age_max['河南'])
        min=int(age_min['河南'])
        mean=float(round(age_mean['河南'],2))
        print(max,type(max))
        print(min,type(min))
        print(mean,type(mean))





    def DataFrame_Group_Other_Teacher(self):  # 3-1分组聚合(其他老师)
        df = pd.DataFrame({"A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
                           "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
                           "C": np.random.randn(8), "D": np.random.randn(8)})
        print(df)
        print('type(df)'.center(60, '-'))
        print(type(df))
        # 1.分组
        group1 = df.groupby(by=['A'])
        group2 = df.groupby(by=['A', 'B'])
        print('type(group1)'.center(60, '-'))
        print(type(group1))
        print('type(group2)'.center(60, '-'))
        print(type(group2))
        '''
            1.group1,group2的类型不是DataFrame,其类型而是DataFrameGroupBy
            2.group1,group2是一个可遍历对象。
            3.groupby中的by参数可以传入单个列标,也可使用列表传入多个列标
        '''
        # 2.groupby之方法
        print("group1.get_group('foo'))".center(60, '-'))
        print(group1.get_group('foo'))  # 获单个条件分组的元素
        print("group2.get_group(('foo','one')))".center(60, '-'))
        print(group2.get_group(('foo', 'one')))  # 获多个条件分组的元素
        print("group1.count()".center(60, '-'))
        print(group1.count())
        print("group2.count()".center(60, '-'))
        print(group2.count())
        print("type(group2.count())".center(60, '-'))
        print(type(group2.count()))
        print(group1['A'].count())  # 好好理解此行代码的含义,参考:选择没有缺失数据的列计算count,即可得出每一个省分的人数
        print(group1['C'].mean())  # 对C列求平均值,其他函数用法参考此该行例子理解
        print(type(group1["A"]))  # 该类型为SeriesGroupBy
        '''
            函数名         说明
            count       分组中非NA值的数量
            sum         非NA值的和
            mean        非NA值的平均值
            median      非NA值的算术中位数
            std. var    无偏(分母为n -1)标准差和方差
            min、 max    非NA值的最小值和最大值

        '''
        # ----------知识拓展:其他三个获取分组后元素的方法
        # 取分组后的元素list方法
        list1 = list(df.groupby(["A"]))
        print(list1[1][1])
        # 取分组后的元素dict方法
        dict1 = dict(list(df.groupby(["A"])))
        print(dict1["bar"])
        # 利用grouby下面的get_group方法
        print(df.groupby(["A"]).get_group('foo'))

    def Recombination_Index(self):  # 4.复合索引
        a = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1), 'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
                          'd': list('hjklmno')})
        print('a'.center(60, '-'))
        print(a)
        print('a.index'.center(60, '-'))
        print(a.index)
        a.index = list('ABCDEFG')
        print(a)
        print('x1'.center(60, '-'))
        x1 = a.reindex(index=list('abcdefg'))  # 好像如果是纯数据类型的DataFrame可以正常显示,下空好好试一下
        print(x1)
        print('x2'.center(60, '-'))
        x2 = a.set_index(['c', 'd'])  # c表示外层索引,d表示内层索引
        print(x2)
        print('type(x2)'.center(60, '-'))
        print(type(x2))
        print('x2.index'.center(60, '-'))
        print(x2.index)
        x3 = a.set_index(['d', 'c'])  # d表示外层索引,c表示内层索引
        print('x3'.center(60, '-'))
        print(x3)
        print('type(x3)'.center(60, '-'))
        print(type(x3))
        print('x3.index)'.center(60, '-'))
        print(x3.index)
        print('x4'.center(60, '-'))
        x4 = x3.swaplevel()  # 表示交换内外层索引的意思
        print(x4)
        print("x4.loc['one'].loc['h']".center(60, '-'))
        print(x4.loc['one'].loc['h'])  # 获取one和h对应的行的数据,两次使用loc方法
        # 获取复合索引的值
        print('x4.index.levels'.center(60, '-'))
        print(x4.index.levels)

        '''
            1.使用复合索引也可以分组            
        '''

    def DataFrame_Data_Concat(self):  # 11.竖向合并concat

        # 1.测试代码
        df1 = pd.DataFrame(np.arange(15).reshape(3, 5), columns=list('ABCDE'))
        df2 = pd.DataFrame(np.arange(100, 120).reshape(4, 5), columns=list('ABCDE'))
        df3 = pd.DataFrame(np.arange(1000, 1035).reshape(7, 5), columns=list('ABCDE'))
        print(df1)
        print(df2)
        print(df3)
        df4 = pd.concat([df1, df2, df3], ignore_index=True)
        print(df4)
        # 2.资料链接
        dialog = QDialog()
        # dialog.resize(300,200)
        dialog.setWindowTitle('学习资料链接')
        lay = QVBoxLayout()
        dialog.setLayout(lay)
        label = QLabel()
        lay.addWidget(label)
        label.setOpenExternalLinks(True)  # 如果不设置此代码,链接点不开
        label.setText('<a href="https://share.weiyun.com/k8MLfpip">腾讯微云:pandas.concat的用法说明.docx</a><br/>'
                      '<a href="https://www.aliyundrive.com/s/RiiLm647PJy">阿里云盘:pandas.concat的用法说明.docx</a>')
        dialog.exec()

    def DataFrame_Date_Range(self):  # 1.时间序列
        t1 = pd.date_range(start='2022-10-1', end='2023-1-1', freq="D")
        print(t1)

    def Func_groupby(self):
        print('测试')
        '''
        语法:
        DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=NoDefault.no_default, observed=False, dropna=True)
        参数:
            by:映射、函数、标签或标签列表
                用于确定 groupby 的组。如果by 是一个函数,它会在对象索引的每个值上调用。如果传递了 dict 或 Series,则 Series 或 dict VALUES 将用于确定组(Series 的值首先对齐;
                参见 .align() 方法)。如果传递了长度等于所选轴的列表或 ndarray(请参阅 groupby 用户指南),则使用这些值 as-is 来确定组。标签或标签列表可以通过 self 中的列传递给分组。
                请注意,元组被解释为(单个)键。

            axis:{0 或 ‘index’,1 或 ‘columns’},默认 0
                沿行 (0) 或列 (1) 拆分。

            level:int,级别名称或此类的序列,默认无
                如果轴是 MultiIndex(分层),则按特定级别或多个级别分组。

            as_index:布尔值,默认为真
                对于聚合输出,返回以组标签为索引的对象。仅与 DataFrame 输入相关。 as_index=False 实际上是 “SQL-style” 分组输出。

            sort:布尔值,默认为真
                对组键进行排序。关闭此函数可获得更好的性能。请注意,这不会影响每组内的观察顺序。 Groupby 保留每个组内的行顺序。

            group_keys:布尔值,默认为真
                调用 apply 时,将组键添加到索引以识别片段。

            squeeze:布尔值,默认为 False
                如果可能,减少返回类型的维数,否则返回一致的类型。

            observed:布尔值,默认为 False
                这仅适用于任何 groupers 是分类的。如果为真:仅显示分类分组的观察值。如果为 False:显示分类分组的所有值。

            dropna:布尔值,默认为真
                如果为 True,并且组键包含 NA 值,则 NA 值连同行/列将被删除。如果为 False,NA 值也将被视为组中的键。
        返回:
            DataFrameGroupBy
            返回包含有关组的信息的 groupby 对象。
        '''
        vip_df = pd.DataFrame(
            {'是否会员': ['vip会员', '超级vip', '普通客户', 'vip会员', '普通客户', 'vip会员', '超级vip'],
             '性别': ['男', '女', '女', '女', '男', '女', '男'],
             '年龄': [25, 30, 40, 25, 40, 18, 30],
             '会员等级': ['LV2', 'LV5', np.nan, 'LV3', 'LV2', 'LV2', 'LV3'],
             '成长值': [180, 425, np.nan, 288, 190, 110, 240]}
        )
        print(vip_df)
        # 1.直接打印groupby对象
        print('1.直接打印groupby'.center(60, '-'))
        df1 = vip_df.groupby(
            by='是否会员')  # 输出结果 <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001BBF8EFD700>
        print(df1)
        '''
        groupby()分组得到的是一个DataFrameGroupBy对象,直接打印DataFrameGroupBy对象只能看到它的内存地址,看不到内部的结构。
        '''
        # 2.DataFrameGroupBy是一个可迭代对象
        print('2.DataFrameGroupBy是一个可迭代对象'.center(60, '-'))
        for name, group in df1:
            print(name)
            print(group)
            print('^' * 29)
        '''
            1.DataFrameGroupBy是一个可迭代对象,可以转换成list打印,也可以直接遍历打印出来。遍历出来的是一个元组,每个元组对应一个分组,
              元组的第一个元素与分组列里的值对应,元组的第二个元素是分到当前小组的数据,是一个DataFrame。
            2.DataFrameGroupBy对象的内部结构为:[(分组名1, 子DataFrame1), (分组名2, 子DataFrame2), ...],
              相当于groupby()将DataFrame按字段值分成了多个小的DataFrame,然后将字段值和小的DataFrame用元组的方式保存在DataFrameGroupBy对象中。
        '''

        # 3.输出多分组的分组名称和分组数据。
        print('3.输出多分组的分组名称和分组数据'.center(60, '-'))
        df2 = vip_df.groupby(by=['是否会员', '性别'])
        for groupby_name, groupby_data in df2:
            print(groupby_name)
            print(groupby_data)
            print('~' * 20)
        '''
        输出结果:
            ('vip会员', '女')
                是否会员 性别  年龄 会员等级    成长值
            3  vip会员  女  25  LV3  288.0
            5  vip会员  女  18  LV2  110.0
            ~~~~~~~~~~~~~~~~~~~~
            ('vip会员', '男')
                是否会员 性别  年龄 会员等级    成长值
            0  vip会员  男  25  LV2  180.0
            ~~~~~~~~~~~~~~~~~~~~
            ('普通客户', '女')
               是否会员 性别  年龄 会员等级  成长值
            2  普通客户  女  40  NaN  NaN
            ~~~~~~~~~~~~~~~~~~~~
            ('普通客户', '男')
               是否会员 性别  年龄 会员等级    成长值
            4  普通客户  男  40  LV2  190.0
            ~~~~~~~~~~~~~~~~~~~~
            ('超级vip', '女')
                是否会员 性别  年龄 会员等级    成长值
            1  超级vip  女  30  LV5  425.0
            ~~~~~~~~~~~~~~~~~~~~
            ('超级vip', '男')
                是否会员 性别  年龄 会员等级    成长值
            6  超级vip  男  30  LV3  240.0
            ~~~~~~~~~~~~~~~~~~~~
            从输出结果中可以看出,groupby这个函数的作用,相当于excel中的筛选功能,参数by相当于excel中的
            设置筛选条件的列名称,这个列名称可以是一个也可以是多个,本循环中的groupby_name相当于设置的筛
            选条件,groupby_data相当筛选条件下对应的筛选出来的数据
        '''
        # 4.获利分组名称
        print('4.获利分组名称'.center(60, '-'))
        print(df1.groups)
        '''
        借用groups可以提取出所有分组的分组名
        '''
        # 5.指定分组对象的名称,获得对应的数据:get_group()方法
        print('5.分组对象的get_group()方法'.center(60, '-'))
        data1 = df1.get_group(name='超级vip')
        print(data1)
        data2 = df2.get_group(name=('vip会员', '女'))
        print(data2)
        '''
            get_group()方法:指定分组对象的名称,获得对应的数据
            name参数的用法:如果单分组即by的分组条件只有一个列索引,name的参数类型是一个字符串,比如name='超级vip'; 
                          如果是多分组即by的分组条件是多个列索引,name的参数是一个元组,比如name=('vip会员', '女')
            df.get_group()的返回结果是一个DataFrame,得到这个结果后,可以对这个数据使用pandas DataFrame的各种统计方法进行统计了
        '''
        # 6.分组对象的统计函数
        print('6.分组对象的统计函数'.center(60, '-'))
        df3 = vip_df.groupby(by=['是否会员', '性别'])  # 获取指定分组的数据
        print(df3)
        print(df3['年龄'].count())
        '''
        输出结果:
            是否会员   性别
            vip会员  女     2
                   男     1
            普通客户   女     1
                   男     1
            超级vip  女     1
                   男     1
            Name: 年龄, dtype: int64
        相当于对所有分组名称下的数据中的“年龄”列的数据使用统计函数count进行统计
        '''

    def set_index(self):
        '''
        set_index
            keys : 要设置为索引的列名(如有多个应放在一个列表里)
            drop : 将设置为索引的列删除,默认为True
            append : 是否将新的索引追加到原索引后(即是否保留原索引),默认为False
            inplace : 是否在原DataFrame上修改,默认为False
            verify_integrity : 是否检查索引有无重复,默认为False

        '''
        # 1.打印原始数据
        print('1.打印原始数据'.center(60, '-'))
        a = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1), 'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
                          'd': list('hjklmno')})
        print(a)
        # 2.将c列d列设置为索引
        print('2.将c列d列设置为索引'.center(60, '-'))
        x2 = a.set_index(['c', 'd'])  # c表示外层索引,d表示内层索引
        print(x2)
        # 3.x2=a.set_index(['c', 'd'])的数据类型
        print("3.x2=a.set_index(['c', 'd'])的数据类型)".center(60, '-'))
        print(type(x2))
        # 4.打印x2的索引值
        print('4.打印x2的索引值'.center(60, '-'))
        print(x2.index)
        # 5.交换set_index传入列索引位置及输出效果
        print('5.交换set_index传入列索引位置及输出效果'.center(60, '-'))
        x3 = a.set_index(['d', 'c'])  # d表示外层索引,c表示内层索引
        print(x3)
        # 6.交换内外层索引顺序的函数
        print('6.交换内外层索引顺序的函数'.center(60, '-'))
        x4 = x3.swaplevel()  # 表示交换内外层索引的意思
        print(x4)
        # 7.获取复合索引的值(未理解,有待研究)
        print('7.获取复合索引的值(未理解,有待研究)'.center(60, '-'))
        print(x4.index.levels)
        # 8.使用复合索引检索数据
        print("8.使用复合索引检索数据".center(60, '-'))
        x5 = x4.loc['one'].loc['h']  # 获取one和h对应的行的数据,两次使用loc方法
        print(x5)
        print(type(x5))
        print(x5['b'])
        get_data = x4.loc['one'].loc['h']['b']
        print(get_data)
        '''
        自己总结的结论:从此代码可以发现检索复合索引数据的方法:从左至若依次输入复合索引的名称,最后在中括号中加一个列名称即可。
            原因:
                1.x5 =x4.loc['one'].loc['h']的数据类型是Series数据类型。
                2.x5['b']相当于使用使用切片功能索引Series中索引为b的数据。
                3.get_data=x4.loc['one'].loc['h']['b']相当上述两步的综合,结论得证。
        '''
        # 9.有关复合索引的数据拼接
        print("9.有关复合索引的数据拼接".center(60, '-'))
        a1 = pd.DataFrame({'a': range(7), 'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
                           'd': list('hjklmno')})

        a2 = pd.DataFrame({'b': range(7, 0, -1), 'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
                           'd': list('hjklmno')})
        print(a1)
        print(a2)
        b1 = a1.set_index(keys=['c', 'd'])
        b2 = a2.set_index(keys=['c', 'd'])
        print(b1)
        print(b2)
        c = b1.join(b2)
        print(c)
        print(x2)
        '''
        对比c和x2可以发现,带有复合索引的DataFrame,同样可以使用jion函数进行数据拼接,至于能否使用merge函数拼接,以后再进行验证。
        '''

    def reset_index(self):
        # reset_index之drop参数的用法
        df = pd.DataFrame(np.arange(20).reshape(5, 4), index=[1, 3, 4, 6, 8])
        print(df)
        # 1.在获得新的index,原来的index变成数据列,保留下来。
        print('1.在获得新的index,原来的index变成数据列,保留下来。'.center(59, '-'))
        df1 = df.reset_index()
        print(df1)
        # 2.不想保留原来的index,使用参数 drop=True,默认 False。
        print('2.不想保留原来的index,使用参数 drop=True,默认 False。'.center(59, '-'))
        df2 = df.reset_index(drop=True)
        print(df2)
        '''
        学习资料:https://www.cnblogs.com/keye/p/11229863.html
        关于其他参数留待以后需要时再学习
        '''

    def reindex(self):
        '''
        reindex() 语法
        DataFrame.reindex(self, labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)

            使用可选的填充逻辑使DataFrame符合新索引。

            labels : 类似数组,可选,新 labels / index "axis"指定的轴与之一致。
            index, columns : 类似数组,可选;要使用的新labels/index 引要符合。最好是一个Index对象,以避免重复数据。
            axis: 默认是 index
            method : {默认 None,'backfill'/'bfill,'pad'/'ffill’, 'nearest'},
                用于在重新索引的DataFrame中填充孔的方法。

                请注意:这仅适用于具有单调递增/递减索引的DataFrames/Series。

                1) None (default): 不填补空白

                2) pad / ffill: 将上一个有效观察值向前传播到下一个有效值。

                3) backfill / bfill: 使用下一个有效观察值填充空白。

                4) nearest: 使用最近的有效观测值来填补空白。

            copy : boolean, 默认 True,即使传递的索引相同,也返回一个新对象。
            level : int 或 name,在一个级别上广播,在传递的MultiIndex级别上匹配索引值。
            fill_value : scalar, 默认为 np.NaN,用于缺失值的值。默认为NaN,但可以是任何“compatible”值。
            limit : int, 默认 None。向前或向后填充的连续元素的最大数量。
            tolerance: 可选。不精确匹配的原始标签和新标签之间的最大距离。
            在匹配位置的索引值最符合公式

            abs(index[indexer] - target) <= tolerance。

            公差可以是一个标量值,它对所有值应用相同的tolerance;

            也可以是类似列表的值,它对每个元素应用可变的tolerance。

            list-like包括list、tuple、array、Series,

            并且必须与索引相同大小,其 dtype 必须与索引的类型完全匹配。
            资料链接:   https://blog.csdn.net/u010701274/article/details/121491114

        '''
        # 1.调用reindex将会重新排序

        print('-' * 6 + '1.调用reindex将会重新排序' + '-' * 6)
        series_1 = pd.Series([1, 7, 3, 9], index=['d', 'c', 'b', 'a'])
        print(series_1)
        series_2 = series_1.reindex(['a', 'b', 'c', 'd'])
        print(series_2)
        # 2.参数method
        print('-' * 6 + '2.参数method' + '-' * 6)
        series_3 = pd.Series(['北京', '上海', '杭州'], index=[0, 2, 4])
        print(series_3)
        series_4 = series_3.reindex(range(6), method='ffill')
        print(series_4)
        series_5 = series_3.reindex(range(6), method='bfill')
        print(series_5)
        # 其他资料来源:帮助理解method=ffill,该资料来源:https://blog.51cto.com/u_15186792/3793362
        print('-' * 10 + '其他资料来源:帮助理解method=ffill' + '-' * 10)
        s2 = pd.Series(['A', 'B', 'C'], index=[1, 5, 10])
        print(s2)
        print(s2.reindex(index=range(15)))  # 默认用nan填充
        print(s2.reindex(index=range(15), method='ffill'))  # 如果新增加索引的值不存在,那么按照前一个非nan的值填充进去
        '''
            传入method=重新索引时选择插值处理方式:
                method=’ffill’或’pad 前向填充,即如果新增加索引的值不存在,那么按照前一个非nan的值填充进去
                method=’bfill’或’backfill 后向填充,道理同上
        '''
        # 3.对DataFrame对象重新索引
        print('-' * 6 + '3.对DataFrame对象重新索引' + '-' * 6)
        df1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'c', 'd'], columns=['one', 'two', 'four'])
        print(df1)
        df2 = df1.reindex(['a', 'b', 'c', 'd'])
        print(df2)
        df3 = df1.reindex(index=['a', 'b', 'c', 'd'], columns=['one', 'two', 'three', 'four'])
        print(df3)

        '''
        自己总结:
            1.由此可见,参数index或columns传入的列表数据个数如果大于行数或列数,多出的行索引或列索引对应的的数据用nan填充
            2.reindex有重新给DataFrame行或列的索引重新排序的功效
        '''
        # 4.传入fill_value=n用n代替缺失值
        print('-' * 6 + '4.传入fill_value=n用n代替缺失值' + '-' * 6)
        df4 = df1.reindex(index=['a', 'b', 'c', 'd'], columns=['one', 'two', 'three', 'four'], fill_value=50)
        print(df4)
        # 5.减小 index相当于切片效果,资料来源:https://blog.51cto.com/u_15186792/3793362
        print('-' * 6 + '5.减小 index相当于切片效果' + '-' * 6)
        df5 = df1.reindex(index=['c', 'd'], columns=['one', 'two'])
        print(df5)
        '''
        1~4参考资料来源:https://blog.csdn.net/wzk4869/article/details/126636727
        '''
        # 6.可以使用 drop,来丢掉某些 index
        df6 = df1.reindex(index=['x', 'y', 'z'], columns=['A', 'B', 'C'], copy=False)
        print(df6)

    def index_columns(self):
        print('对比学习总结index和columns')

    def Quantile_Function(self):
        print('分位数')
        '''
        分位数的概念
            分位数(Quantile),亦称分位点,是指将一个随机变量的概率分布范围分为几个等份的数值点,常用的有中位数(即二分位数)、四分位数、百分位数等。
            Series和DataFrame均可以使用分类函数。
            相关知识点见参数资料。
        '''
        # 1.DataFrame之分类数
        df = pd.read_excel('./LoadFile/学生成绩_分位数.xlsx')
        print(df)
        print(df.quantile(0.1))
        print(df.quantile(0.25, axis=1))
        # 2.Series之分位数
        list1 = [70, 72, 73, 75, 78, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 93, 94, 94, 95, 96,
                 97, 98, 99, 100]
        t1 = pd.Series(list1)
        print(t1)
        print(t1.quantile(0.25))
        '''
        分位数函数的参数意义:
            q : 数字或者是类列表,范围只能在0-1之间,默认是0.5,即中位数-第2四分位数
            axis :计算方向,可以是 {0, 1, ‘index’, ‘columns’}中之一,默认为 0
            interpolation(插值方法):可以是 {‘linear’, ‘lower’, ‘higher’, ‘midpoint’, ‘nearest’}之一,默认是linear。
            这五个插值方法是这样的:当选中的分为点位于两个数数据点 i and j 之间时:
            linear: i + (j - i) * fraction, fraction由计算得到的pos的小数部分(后面有例子);
            lower: i.
            higher: j.
            nearest: i or j whichever is nearest.
            midpoint: (i + j) / 2.
        '''
        # 3.资料链接
        dialog = QDialog()
        # dialog.resize(300,200)
        dialog.setWindowTitle('学习资料链接')
        lay = QVBoxLayout()
        dialog.setLayout(lay)
        label = QLabel()
        lay.addWidget(label)
        label.setOpenExternalLinks(True)  # 如果不设置此代码,链接点不开
        label.setText('<a href="https://share.weiyun.com/1ZRoIrJ5">腾讯微云:pandas分位数相关知识.docx</a><br/>'
                      '<a href="https://www.aliyundrive.com/s/j4XMZtkZYBs">阿里云盘:pandas分位数相关知识.docx</a>')
        dialog.exec()

    def Func_apply(self):
        '''
        1.基本信息:
            pandas 的 apply() 函数可以作用于 Series 或者整个 DataFrame,功能也是自动遍历整个 Series 或者 DataFrame,
            对每一个元素运行指定的函数。(个人理解:apply功能也是自动遍历整个 Series 或者 DataFrame, 对【指定范围内的】每一个元素运行指定的函数。)
        2.语法结构
            apply() 使用时,通常放入一个 lambda 函数表达式、或一个函数作为操作运算,官方上给出DataFrame的 apply() 用法:
            参数:

                func 代表的是传入的函数或 lambda 表达式;
                axis 参数可提供的有两个,该参数默认为0/列
                    0 或者 index ,表示函数处理的是每一列;
                    1 或 columns ,表示处理的是每一行;
                    此参数的含义是:可以描述为axis=0或axis=’index‘
                raw ;bool 类型,默认为 False;
                    False ,表示把每一行或列作为 Series 传入函数中;
                    True,表示接受的是 ndarray 数据类型;
                result_type:{‘expand’, ‘reduce’, ‘broadcast’, None}, default None
                    These only act when axis=1 (columns):

                    ‘expand’ : 列表式的结果将被转化为列。
                    ‘reduce’ : 如果可能的话,返回一个 Series,而不是展开类似列表的结果。这与 expand 相反。
                    ‘broadcast’ : 结果将被广播到 DataFrame 的原始形状,原始索引和列将被保留。
                args: func 的位置参数。(个人理解)见本笔记传入多参数的用法
                **kwargs:要作为关键字参数传递给 func 的其他关键字参数,1.3.0 开始支持。(个人理解)作用:应同args一样,
                          属于如何设置传递被调用函数的多参数的功能,经测试验证了自己的判断。

            数据以 Series 或 DataFrame 格式返回。
        '''
        df = pd.DataFrame([[4, 9, 16], [25, 36, 49], [64, 81, 100]], columns=list('ABC'))
        print(df)
        # apply使用numpy的通用函数
        print('apply使用numpy的通用函数'.center(100, '-'))
        df1 = df.apply(np.sqrt)
        print(df1)
        # 参数axis=0同axis="index"等效
        print('参数axis=0同axis="index"等效'.center(100, '-'))
        df_axis_0 = df.apply(np.sum, axis=0)
        print(df_axis_0)
        df_axis_index = df.apply(np.sum, axis='index')
        # 测试axis=1的设置
        print('测试axis=1的设置'.center(100, '-'))
        df3 = df.apply(np.sum, axis=1)
        print(df3)
        # apply中传入lambda表壳式
        print('apply中传入lambda表壳式'.center(100, '-'))
        df4 = df.apply(lambda x: [1, 2], axis=1)
        print(df4)
        # 函数里面可以再次定义函数
        print('函数里面可以再次定义函数'.center(100, '-'))

        def square(x):
            return x ** 2

        df5 = df.apply(square)
        print(df5)
        # apply调用自定义函数时,函数名后面没有小括号
        print('apply调用自定义函数时,函数名后面没有小括号'.center(100, '-'))
        df6 = df['A'].apply(square)
        print(df6)
        # apply传递含有两个参数的函数的一种方法
        print('apply传递含有两个参数的函数的一种方法'.center(100, '-'))

        def lifang(x, e):
            return x ** e

        df7 = df.apply(lifang, e=3)
        print(df7)
        # 小案例: Pandas的apply方法
        print('小案例: Pandas的apply方法'.center(100, '-'))
        '''
        小案例: Pandas的apply方法
            资料连接:http://www.360doc.com/content/21/0223/14/73874201_963541934.shtml
        '''
        mact = [['张三', '1995-12-31', '山东', '本科'],
                ['李四', '1993-05-29', '河北', '大专'],
                ['王五', '1995-03-14', '山西', '硕士'],
                ['赵六', '1992-07-18', '内蒙古', '本科']]
        data = pd.DataFrame(mact, columns=['姓名', '出生日期', '籍贯', '学历'])
        print(data)

        def year(x):
            return int(x[0:4])

        # 使用apply对DataFrame中列的操作
        print('使用apply对DataFrame中列的操作'.center(100, '-'))
        data['出日年份'] = data['出生日期'].apply(year)  # 该行代码表示增加列,具体知识见增加列相关笔记
        print(data)
        # DataFrame中数字与列中数据之间的去处,具体内容参见Series与数据之间的去处规律
        print('DataFrame中数字与列中数据之间的去处,具体内容参见Series与数据之间的去处规律'.center(100, '-'))
        data['年龄'] = 2023 - data['出日年份']
        print(data)
        # 使用apply对DataFrame进行列间计算,未看明白函数参数t的使用方法
        print('使用apply对DataFrame进行列间计算,未看明白函数参数t的使用方法'.center(100, '-'))

        def intro(t):  # 未看明白
            # t代指DataFrame中任意行,是series类型数据,拥有类似字典的使用方法。
            return '大家好,我是{},来自{}省,今年{}岁了'.format(t['姓名'], t['籍贯'], t['年龄'])

        data['描述信息'] = data.apply(intro, axis='columns')
        print(data)
        # 测试DataFrame列的另外一种表示方法df.列名
        print('测试DataFrame列的另外一种表示方法df.列名'.center(100, '-'))
        data['双倍年龄'] = data.年龄 * 2
        print(data)
        '''搞清楚"data.年龄"这个语法'''

        # aplly传入的函数带有多个参数
        print('aplly传入的函数带有多个参数'.center(100, '-'))

        '''
            apply传入的参数是函数名称,如果函数带多个参数怎么办? apy给了一个args这个关键字参数,后面接一个元组,
            把需要传入的参数加进去,此时传入的元组不用算第一个参数,这也是一般常见的传参模式。
            学习资料连接:https://wenku.baidu.com/view/e06fd538ff4ffe4733687e21af45b307e871f97d.html?_wkts_=1681807109157&bdQuery=pandas+apply+%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0
        '''

        def morecanshu(a, b, c, d):
            return a + b + c + d

        data['测试多参数'] = data['年龄'].apply(morecanshu, args=(10, 20, 30))
        print(data)
        # 测试使用**kwargs传递多参数
        print('测试使用**kwargs传递多参数'.center(100, '-'))
        data['**kwargs传递多参数'] = data['年龄'].apply(morecanshu, b=10, c=20, d=30)
        print(data)

        # 自己总结的资料2023-5-10

        # 含有nan的两列数据的加减
        print('含有nan的两列数据的加减'.center(60, '-'))
        V1 = pd.DataFrame(np.arange(36).reshape(9, 4), columns=list('ABCD'))
        print(V1)

        def plus(t, a, b):  # 两列数据之间的运算(使用变量表示列索引)
            return t[a] + t[b]  # 如果某列数据中有一个数据为NaN,该数据同其他列数据进行运算时为NaN,但不影响其他正常数据的运算

        V1.loc[2, 'A'] = np.NaN  # A列第3行对应的数据赋值为NaN
        print(V1)  # A列第3行数据赋值为NaN后的输出结果
        V1["E"] = V1.apply(plus, a='A', b='B', axis=1)
        V1["F"] = V1.apply(plus, a='B', b='C', axis=1)
        print(V1)
        a = "B"
        print(V1[a])  # E列第3行对应数据的计算结果也是NaN,本说明可以解释plus函数return语句的注释
        # 测试判断函数
        print('测试判断函数'.center(60, '-'))
        list1 = [random.randint(0, 99) for i in range(36)]
        n = np.array(list1).reshape(9, 4)
        V2 = pd.DataFrame(data=n, columns=list('ABCD'))
        print(V2)

        def judge(t, a, b, c, p):  # 判断a,b,c三列同一行的数据,是否大于p的函数
            '''
            :param t: 好像表示DataFrame数据,该参数见关于apply内容上面的讲解
            :param a: 表示df的列名的变量
            :param b: 表示df的列名的变量
            :param c: 表示df的列名的变量
            :param p: 判断标准的值,当a,b,c三列对应同一行的数值均大于p,返回Y,否则返回N
            :return: 满足判断条件返回Y,否则返回N
            '''
            if t[a] > p and t[b] > p and t[c] > p:  # t[a] 使用变量表示DataFrame的列
                return 'Y'
            else:
                return 'N'

        V2['判断结果'] = V2.apply(judge, a='A', b='B', c='C', p=25, axis=1)  # aplly传入多参数的函数,同时再传入坐标轴
        print(V2)

    def Add_columns(self):
        '''
        要求熟练掌握前面三种方法。
        参考资料:https://www.jb51.net/article/251192.htm
        '''
        mact = [['张三', '1995-12-31', '山东', '本科'],
                ['李四', '1993-05-29', '河北', '大专'],
                ['王五', '1995-03-14', '山西', '硕士'],
                ['赵六', '1992-07-18', '内蒙古', '本科']]
        data = pd.DataFrame(mact, columns=['姓名', '出生日期', '籍贯', '学历'])
        print(data)
        # 1.直接赋值法
        print('1.直接赋值法'.center(60, '-'))
        # 增加‘导师’列
        data['导师'] = ['张老师', '李老师', '王老师', '周老师']
        print(data)
        # 2.loc()函数法
        print('2.loc()函数法'.center(60, '-'))
        # 增加"电话"列
        data.loc[:, '电话'] = [10086, 10000, 10010, 10099]
        print(data)
        # 3.insert()函数法
        print('3.insert()函数法'.center(60, '-'))
        '''
        语法:DataFrame.insert(loc, column, value,allow_duplicates = False)
            参数                  说明
            loc                 int类型数据,表示插入新列的列位置,原来在该位置的列将向右移。
            column              插入新列的列名。
            value               新列插入的值。如果仅提供一个值,将为所有行设置相同的值。可以是int,string,float等,甚至可以是series /值列表。
            allow_duplicates    布尔值,用于检查是否存在具有相同名称的列。默认为False,不允许与已有的列名重复。
        '''
        data.insert(loc=1, column='性别', value=['男', '女', '女', '男'])
        print(data)
        # 4.reindex()函数法
        print('reindex()函数法'.center(60, '-'))
        d = data.columns
        new_df = data.reindex(columns=['姓名', '性别', '出生日期', '籍贯', '学历', '导师', '电话', '民族'],
                              fill_value='汉族')
        print(new_df)

    def Series_Calculate(self):
        '''
        参数资料:https://zhuanlan.zhihu.com/p/32279748
        '''
        t1 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'c', 'a'])
        print(t1)
        # 1.Series与数字的运算
        print('1.Series与数字的运算'.center(60, '-'))
        print(t1 * 2)  # 乘法
        print(t1 + 2)  # 加法
        # 2.Series与Series运算
        print('1.Series与数字的运算'.center(60, '-'))
        '''
        运算规律:
            相同索引位置的数据进行运算,不同索引位置的运算结果为nan
        '''
        t2 = pd.Series([2, -8, 1, 6], index=['d', 'b', 'c', 'a'])
        t3 = pd.Series([2, -8, 1, 6], index=['d', 't', 'c', 'a'])
        print(t1 + t2)  # 两个Series索引完全相同
        print(t1 + t3)  # 两个Series索引不完全相同
        # 3.Series的布尔运算
        print('3.Series的布尔运算'.center(60, '-'))
        print(t1 > 3)

    def AdjustColumns(self):
        mact = [['张三', '1995-12-31', '山东', '本科'],
                ['李四', '1993-05-29', '河北', '大专'],
                ['王五', '1995-03-14', '山西', '硕士'],
                ['赵六', '1992-07-18', '内蒙古', '本科']]
        data = pd.DataFrame(mact, columns=['姓名', '出生日期', '籍贯', '学历'])
        print(data)
        # 1.好好琢磨此种改变列顺序的方法
        print('1.好好琢磨此种改变列顺序的方法'.center(60, '-'))
        new = data[['姓名', '学历', '籍贯', '出生日期']]  # 双中括号,中括号的列表仅仅调整了列索引的位置,输出的新dataframe就完成了列顺序调整
        print(new)
        # 2.使用reindex方法调整DataFrame列顺序
        print('2.使用reindex方法调整DataFrame列顺序'.center(60, '-'))
        reindex_data = data.reindex(columns=['学历', '姓名', '籍贯', '出生日期'])
        print(reindex_data)

    def Data_Cleaning(self):
        '''

        优质学习资料链接:https://blog.csdn.net/m0_46336403/article/details/119852595
        '''
        # 剑客一:drop
        print('剑客一:df.drop'.center(80, '-'))
        ''' 
        drop函数:用来删除数据表格中的列数据或行数据      
            参数	    简介
            labels	以列表形式赋值,待删除的行名或列名,与axis参数一起使用
            axis	确定删除行还是列,0为行,1为列
            index	以列表形式赋值,删除第几行;不与labels和axis参数连用
            columns	以列表形式赋值,删除第几列;不与labels和axis参数连用
            inplace	是否用新生成的列表替换原列表
        '''
        df = pd.DataFrame(np.arange(16).reshape(4, 4), columns=list('ABCD'))
        print(df)
        print('使用labels+axis两个参数删除行,删除列同理'.center(59, '*'))
        t1 = df.drop(labels=[1, 2], axis=0)
        print(t1)
        print('使用index参数删除行,删除列同理'.center(59, '*'))
        t2 = df.drop(index=[0, 1])
        print(t2)
        print('将inplace参数设置为True,则生成的DataFrame替换掉原DataFrame'.center(59, '*'))
        df.drop(index=[0, 1], inplace=True)
        print(df)
        # 剑客二:df.dropna
        print('df.dropna'.center(80, '-'))
        '''
        dropna函数:用来删除数据表格中的空值数据
            参数	简介
            axis	数据删除维度,参数值可以为0,1或index,columns
            how	any:删除带有nan的行;all:删除全为nan的行
            subset	删除指定列空值数据
            inplace	是否用新生成的列表替换原列表
        '''
        data = pd.DataFrame({'name': ["Alfred", 'Batman', np.nan], 'toy': [np.nan, "Batmobile", np.nan],
                             'born': [pd.NaT, pd.Timestamp('1940-04-25'), pd.NaT]})
        print(data)
        # 1.删除带空值的行
        print('删除带空值的行'.center(59, '*'))
        d1 = data.dropna(axis='index', how='any', inplace=False)  # 任何出现空值的行
        print(d1)
        # 2.删除带空值的列
        print('删除带空值的列'.center(59, '*'))
        d2 = data.dropna(axis=1, how='all', inplace=False)  # 全部为空值的列
        print(d2)
        # 3.删除指定列存在空值的行
        print('删除指定列存在空值的行'.center(59, '*'))
        d3 = data.dropna(axis=0, subset=['name'], how='any', inplace=False)
        print(d3)
        # 剑客三:df.drop_duplicates
        print('剑客三:df.drop_duplicates'.center(80, '-'))
        '''
        drop_duplicates函数:用来去除数据表格中的重复数据
            参数	简介
            subset	以列表形式赋值,需去重的列
            keep	“first”:仅保留第一次出现的重复行;“last”:仅保留最后一次出现的重复行;False:删除全部重复行
            inplace	是否用新生成的列表替换原列表
        '''
        dup = pd.DataFrame({'第一列': [1, 1, 3, 4, 5, 3, 4, 5],
                            '第二列': [1, 1, 20, 20, 30, 40, 50, 50],
                            '第三列': [1, 1, 20, 20, 200, 600, 500, 600],
                            '第四列': [1, 1, 's', 'd', 'a', 'b', 's', 'a']})
        print(dup)
        # 1.方法一:对整个表格,所有数据完全相同的行进行去重,并保留第一次出现的行
        print('方法一:对整个表格,所有数据完全相同的行进行去重,并保留第一次出现的行'.center(59, '*'))
        dp1 = dup.drop_duplicates(subset=None, keep='first', inplace=False)
        print(dp1)
        # 2.方法二:删除所有重复的行
        print('方法二:删除所有重复的行'.center(59, '*'))
        dp2 = dup.drop_duplicates(subset=None, keep=False, inplace=False)
        print(dp2)
        '''
            该示例原资料有错误,若做到学习资料显示效果,keep参数应为False。
        '''
        # 3.方法三:对指定列进行去重
        print('方法三:对指定列进行去重'.center(59, '*'))
        dp3 = dup.drop_duplicates(subset=['第二列', '第三列'], keep='last', inplace=False)
        print(dp3)
        '''
            该示例原资料有错误。若做到学习资料显示效果,keep参数应为last。
        '''
        # 4.reset_index函数重新设置索引
        print('4.reset_index函数重新设置索引'.center(59, '*'))
        dp4 = dup.drop_duplicates(subset=['第二列'], keep=False, inplace=False)
        print(dp4)
        print('reset_index示例'.center(59, '*'))
        dp5 = dp4.reset_index(drop=False)
        print(dp5)
        '''
        不想保留原来的index,则使用参数drop=True
        '''

    def ManySeriesToDataFrame(self):
        # 1.行索引完全相同的三个Series合并为DataFrame效果
        print('1.行索引完全相同的三个Series合并为DataFrame效果'.center(59, '-'))
        s1 = pd.Series([1, 2, 3], index=['X', 'Y', 'Z'])
        s2 = pd.Series(['a', 'b', 'c'], index=['X', 'Y', 'Z'])
        s3 = pd.Series([4.5, 5.5, 6.5], index=['X', 'Y', 'Z'])
        df1 = pd.DataFrame({'columns': s1, 'columns2': s2, 'columns3': s3})
        print(df1)

        # 2.行索引不完全相同的三个Series合并为DataFrame效果
        print('2.行索引不完全相同的三个Series合并为DataFrame效果'.center(59, '-'))
        t1 = pd.Series([1, 2, 3], index=['X', 'Y', 'Z'])
        t2 = pd.Series(['a', 'b', 'c'])
        t3 = pd.Series([4.5, 5.5, 6.5])
        df2 = pd.DataFrame({'columns': t1, 'columns2': t2, 'columns3': t3})
        print(df2)
        '''
        学习资料来源:https://blog.csdn.net/qq_41517071/article/details/128274070
        '''

    def DataFrameSort(self):
        # 1.DataFrame原始数据
        print('1.DataFrame原始数据'.center(69, '-'))
        list1 = [random.randint(0, 99) for i in range(36)]
        n = np.array(list1).reshape(9, 4)
        V2 = pd.DataFrame(data=n, columns=list('ABCD'), index=list('hyioplmde'))
        print(V2)
        # 2.按行索引排序
        print('2.按行索引排序'.center(69, '-'))
        V2.sort_index(ascending=True, inplace=True)
        print(V2)
        # 3.按某一列的值排序
        print('3.按某一列的值排序'.center(69, '-'))
        V2.sort_values(by='B', ascending=True, inplace=True)
        print(V2)
        '''
        学习方法:
            1.参数及理解方法可以Series排序方法理解,参数基本上同Series排序的参数
            2.待到有需要时,再做深入研究
        可以参数的学习资料(参考价值不大):https://blog.csdn.net/wzk4869/article/details/126370595
        '''


app = QApplication(sys.argv)
w = MyWin()
w.show()
app.exec()

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值