--- slide1.xml --- 授课教师:李 老师 第4章 Pandas数据分析库 --- slide2.xml --- 本章学习目标 01 了解Pandas数据分析库以及数据结构的基本概念。 03 熟悉Pandas中数据框的索引、切片、布尔索引等数据选择技术,以及如何进行数据的合并、连接和转换。 05 学习Pandas中的数据清洗技巧,包括处理缺失值、异常值、重复值,以及数据类型转换,确保数据质量。 02 掌握利用Pandas进行数据结构创建与操作。 04 理解Pandas在处理时间序列数据时的优势,包括时间序列的生成、索引设置、时间间隔计算、重采样、移动窗口计算和时间序列数据分析。 06 培养使用Pandas解决实际数据分析问题的能力。 --- slide3.xml --- 目录 4.2 数据选择与过滤 4.3 数据 分组与聚合 4.4 合并和连接 4.1 Pandas数据结构的创建与操作 4.5 数据读取和存储 4.6 数据清洗和预处理 4.7 时间序列处理 --- slide4.xml --- pandas导入惯例 import pandas as pd 01 from pandas import Series 02 from pandas import DataFrame 03 --- slide5.xml --- 4.1 Pandas数据结构的创建与操作 序列创建与基本操作 4.1.1 数据框创建与基本操作 4.1.2 --- slide6.xml --- 4.1 Pandas数据结构的创建与操作 序列 概念:序列是用于存储一维数组的结构。 要素:一组数据和对应的索引,索引可以是默认的整数索引或用户自定义的标签。 --- slide7.xml --- 4.1.1 序列创建与基本操作 1. 创建方法 实例演示 (1)用列表作为参数,并且不指定索引,自动生成整数索引 In: a = Series([6.3, 43.1, 24.4]) a Out: 0 6.3 1 43.1 2 24.4 dtype: float64 --- slide8.xml --- 4.1.1 序列创建与基本操作 1. 创建方法 实例演示 (2)用numpy数组作为参数,并且用index参数指定标签。 In: chengji = Series(np.array((70,85,90)), index=['语文', '数学', '英语']) chengji Out: 语文 70 #标签表示课程,值表示分数 数学 85 英语 90 --- slide9.xml --- 4.1.1 序列创建与基本操作 2. 修改序列对象的 标签 实例演示 创建序列对象后通过该对象的index属性修改标签。 In: gu = Series([6.3, 43.1, 24.4]) gu.index=['幸福银行', '平安科技', '南方通信'] gu Out: 幸福银行 6.3 #标签表示股票的名称,值表示股票的价格 平安科技 43.1 南方通信 24.4 对比有标签的对象和没有标签的对象 , 区别在哪里? --- slide10.xml --- 4.1.1 序列创建与基本操作 3. 访问 对象的元素 实例演示 (1)通过索引。无论对象有无标签,都可以通过索引访问其中的元素。 (2)通过标签。当对象有标签时,可以通过标签访问对应的元素。通过自定义标签,用户可以方便地理解和访问数据,而不需要依赖整数索引。 In: a[1] Out: 43.1 In: gu[2] Out: 24.4 In: chengji['数学'] Out: 85 In: gu['南方通信'] Out: 24.4 --- slide11.xml --- 4.1.1 序列创建与基本操作 4. 对序列对象切片 实例演示 对序列对象切片,切片得到的是原始对象的视图。有如下方法。 (1)索引切片。通过索引切片与对Python可迭代对象切片的方法相同。 (2)标签切片。通过标签切连续的元素,语法格式如下: 对象['起始标签': '结束标签'] In: gu[0:2] Out: 幸福银行 6.3 平安科技 43.1 In: gu['平安科技':'南方通信'] Out: 平安科技 43.1 南方通信 24.4 --- slide12.xml --- 4.1.1 序列创建与基本操作 5. 增加元素和修改序列元素 实例演示 创建好序列对象后,还可以增加元素和修改其中的元素,方法与Python字典对象相同,语法格式如下: 对象['标签1'] = 值 当原对象中存在标签1时,该语句修改它的值。反之,则在其中增加标签1,以及对应的值。 In: gu['南方通信'] = 25.3 gu['光明证券'] = 17.78 gu Out: 幸福银行 6.30 平安科技 43.10 南方通信 25.30 #修改了元素值 光明证券 17.78 #增加了一个元素 --- slide13.xml --- 4.1.1 序列创建与基本操作 6. 删除元素 实例演示 使用序列对象的drop()方法来删除一个或多个元素。通过指定元素的标签,drop()删除指定元素并返回一个新序列对象,其中不包含被删除的元素。需要注意的是,drop()默认不会修改原始序列,除非使用inplace=True参数。 ( 1 )删除单个元素时,直接将元素的标签值传给drop函数。 In: gudel = gu.drop('光明证券') gudel #新对象删除了光明证券 Out: 幸福银行 6.3 平安科技 43.1 南方通信 25.3 --- slide14.xml --- 4.1.1 序列创建与基本操作 6. 删除元素 实例演示 ( 2 )删除多个元素时,将多个标签值封装到一个列表传给drop函数,列表中标签的顺序可以与序列对象中的顺序不同。 ( 3 )如果要在原始对象序列中删除指定标签值,需要指定inplace参数。 In: gudel = gu.drop(['光明证券','平安科技']) gudel #新对象删除了光明证券和平安科技 Out: 幸福银行 6.3 南方通信 25.3 In: gu.drop('光明证券', inplace=True) gu #在原始对象中删除了光明证券 Out: 幸福银行 6.3 平安科技 43.1 南方通信 25.3 --- slide15.xml --- 4.1.1 序列创建与基本操作 7. 运算操作 实例演示 序列对象支持多种运算操作,如数值运算、逻辑运算等,且这些运算能够在整个数据序列上高效执行。 In: open = Series([23.5, 6.1, 42.1], index=['南方通信', '幸福银行', '平安科技']) open + 1.0 Out: 南方通信 24.5 幸福银行 7.1 平安科技 43.1 In: open > 10.0 Out: 南方通信 True 幸福银行 False 平安科技 True --- slide16.xml --- 4.1.1 序列创建与基本操作 7. 运算操作 实例演示 序列之间也可以进行运算,Pandas 会根据索引对齐数据进行操作。即使两个序列的索引不同,也能自动处理数据的对齐问题,自动对齐大大提升了数据操作的灵活性和简便性,使得数据分析变得更加高效、可靠。 In: close = Series([44.3, 22.6, 6.5], index=['平安科技', '南方通信', '幸福银行', ]) close – open Out: 南方通信 -0.9 平安科技 2.2 幸福银行 0.4 两个序列对象的索引顺序不同,系统自动处理数据对齐。 --- slide17.xml --- 4.1.2 数据框创建与基本操作 1. 创建数据 框 实例演示 数据框是一种二维的数据结构,用于存储和处理表格数据,它具有行和列的标签。 创建数据框对象时需要分别指定行、列标签。 常用两种方法 创建数据框。 (1)从字典创建。字典的键成为列标签,再用index参数指定行标签。 In: data = {'平安科技':[45.2,47.1,46.5,49.8], '南方通信':[31.9,27.3,25.2,24.5], '幸福银行':[3.4,4.6,5.2,6.8]} df = DataFrame(data, index=['2024-01','2024-02','2024-03','2024-04']) df Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 2024-03 46.5 25.2 5.2 2024-04 49.8 24.5 6.8 --- slide18.xml --- 4.1.2 数据框创建与基本操作 1. 创建数据 框 实例演示 (2)从二维列表创建。二维列表的元素成为数据框的行数据,再用index参数指定行标签和columns参数指定列标签。 In: data = [[45.2,31.9,3.4], [47.1,27.3,4.6], [46.5,25.2,5.2], [49.8,24.5,6.8]] col=['平安科技', '南方通信', '幸福银行'] ind=['2024-01','2024-02','2024-03','2024-04'] df = DataFrame(data, columns=col, index=ind) df Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 2024-03 46.5 25.2 5.2 2024-04 49.8 24.5 6.8 --- slide19.xml --- 4.1.2 数据框创建与基本操作 2. 在数据框末尾追加新行 实例演示 创建数据框对象后,在pandas 2.x版本中,使用concat()方法在数据框末尾追加新行。 In: new_row = pd.DataFrame({'平安科技':45.6, '南方通信':26.4, '幸福银行':5.8}, index=['2024-05']) #新行也是一个数据框 df = pd.concat([df, new_row]) Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 2024-03 46.5 25.2 5.2 2024-04 49.8 24.5 6.8 2024-05 45.6 26.4 5.8 --- slide20.xml --- 4.1.2 数据框创建与基本操作 2. 在数据框末尾追加新行 实例演示 在pandas 1.x版本中,可以通过append()方法在数据框末尾追加新行。该方法的参数可以是一个字典或者序列对象,结果有两种情况。 (1)参数是序列对象,且包含name属性。序列对象的数据添加到数据框对象的末尾,它的name属性作为新行的行标签。 In: s = pd.Series({'平安科技':45.6, '南方通信':26.4, '幸福银行':5.8}, name='2024-05') df.append(s) Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 2024-03 46.5 25.2 5.2 2024-04 49.8 24.5 6.8 2024-05 45.6 26.4 5.8 #name 作为行标签 --- slide21.xml --- 4.1.2 数据框创建与基本操作 2. 在数据框末尾追加新行 实例演示 (2)参数是字典或者无name属性的序列对象。需要通过设置ignore_index=True来自动生成新的行索引。 append方法生成一个新数据框对象,而不修改原始对象。如果要修改原始对象,只需将它的返回值赋值给原对象,如: df = df.append(参数) In: df.append({'平安科技':45.6, '南方通信':26.4, '幸福银行':5.8}, ignore_index=True) Out: 平安科技 南方通信 幸福银行 0 45.2 31.9 3.4 #新生成的对象重建了行标签 1 47.1 27.3 4.6 2 46.5 25.2 5.2 3 49.8 24.5 6.8 4 45.6 26.4 5.8 --- slide22.xml --- 4.1.2 数据框创建与基本操作 3. 增加新列 实例演示 可以直接通过赋值的方式增加新列,格式如下: 对象['新列名'] = 数据 #数据可以是列表和序列对象,长度要与原对象相同。 In: df['三一重工'] = [14.2, 15.6, 17.8, 16.5] Out: 平安科技 南方通信 幸福银行 五一重工 2024-01 45.2 31.9 3.4 14.2 2024-02 47.1 27.3 4.6 15.6 2024-03 46.5 25.2 5.2 17.8 2024-04 49.8 24.5 6.8 16.5 --- slide23.xml --- 4.1.2 数据框创建与基本操作 4. 删除行和列 实例演示 数据框对象的drop方法可以用来删除行和列,该方法的格式如下: 对象.drop('标签名',axis, inplace) 删除行时标签名为行标签名,axis为0或者不提供该参数。 删除列时标签名为列标签名,axis为1。 inplace的值为True直接修改原始对象,否则生成一个新对象。 In: df.drop('2024-02') #删除一行 Out: 平安科技 南方通信 幸福银行 五一重工 2024-01 45.2 31.9 3.4 14.2 2024-03 46.5 25.2 5.2 17.8 2024-04 49.8 24.5 6.8 16.5 In: df.drop('幸福银行', axis=1) #删除一列 Out: 平安科技 南方通信 五一重工 2024-01 45.2 31.9 14.2 2024-02 47.1 27.3 15.6 2024-03 46.5 25.2 17.8 2024-04 49.8 24.5 16.5 --- slide24.xml --- 4.1.2 数据框创建与基本操作 5. 对数据进行排序 实例演示 sort_values()方法用于根据指定列或索引对数据进行排序。它能够对一列或多列的数据按升序或降序排列,默认情况下为升序。 In: data = {'姓名': ['张军', '王怡', '李和'], '年龄': [25, 30, 25], '体重':[67, 82, 76] } df = pd.DataFrame(data) df.sort_values(by = '体重') #按体重升序排序 Out: 姓名 年龄 体重 2 李和 25 76 0 张军 25 67 1 王怡 30 82 In: df.sort_values(by = '体重', ascending=False) #降序排序 Out: 姓名 年龄 体重 1 王怡 30 82 0 张军 25 67 2 李和 25 76 --- slide25.xml --- 4.1.2 数据框创建与基本操作 5. 对数据进行排序 实例演示 sort_values()方法用于根据指定列或索引对数据进行排序。它能够对一列或多列的数据按升序或降序排列,默认情况下为升序。 In: df.sort_values(by = ['年龄','体重']) #两个排序关键字,先按年龄排序,如果年龄相同则按体重排 Out: 姓名 年龄 体重 2 李和 25 76 0 张军 25 67 1 王怡 30 82 --- slide26.xml --- 4.2 数据选择与过滤 4. 2.3多条件联合筛选 4. 2.2 基于条件的数据筛选 4. 2.1 使用选择器和快速访问器 --- slide27.xml --- 4.2.1 使用选择器和快速访问器 1. 按列 访问 实例演示 按列访问数据框时,有以下两种语法形式: 对象名['列标签'] #列标签要加引号 对象名.列标签 #列标签不加引号 对象名['列标签'] :列标签作为字符串处理,引号是必要的,可以处理任意字符的列标签。 对象名.列标签 :这是通过数据框的属性访问列。引号不需要,这种方式对列标签的要求较严格,不能有空格、特殊字符,且不能与已有的方法或属性重名。 In: df['平安科技'] Out: 2024-01 45.2 2024-02 47.1 2024-03 46.5 2024-04 49.8 Name: 平安科技, dtype: float64 In: df.南方通信 Out: 2024-01 31.9 2024-02 27.3 2024-03 25.2 2024-04 24.5 Name: 南方通信, dtype: float64 --- slide28.xml --- 4.2.1 使用选择器和快速访问器 1. 按列 访问 实例演示 访问一列后,如果还要继续访问其中的一个元素,则按照访问序列对象的方法,如: 对象名['列标签'][ '行标签'] #注意:列标签在前,行标签在后 In: df["平安科技"]['2024-02'] Out: 47.1 --- slide29.xml --- 4.2.1 使用选择器和快速访问器 1. 按列 访问 实例演示 数据框按列访问不支持切片,但是支持索引标签切片,语法格式为: 对象名[['列标签',…]]: In: df[['平安科技', '幸福银行']] Out: 平安科技 幸福银行 2024-01 45.2 3.4 2024-02 47.1 4.6 2024-03 46.5 5.2 2024-04 49.8 6.8 --- slide30.xml --- 4.2.1 使用选择器和快速访问器 2. 按 行访问 实例演示 按行访问需要用选择器loc和iloc ,有多种形式,如表4-1所示。 loc通过标签来进行数据访问 iloc通过整数索引来进行数据访问 In: df.loc['2024-01'] Out: 平安科技 45.2 南方通信 31.9 幸福银行 3.4 Name: 2024-01, dtype: float64 In: df.iloc[1] Out: 平安科技 47.1 南方通信 27.3 幸福银行 4.6 Name: 2024-02, dtype: float64 --- slide31.xml --- 4.2.1 使用选择器和快速访问器 2. 按 行访问 实例演示 访问一行后,如果还要继续访问其中的一个元素,则按照访问序列对象的方法,如: 对象名.loc[ '行标签'] ['列标签'] #注意:行标签在前,列标签在后 对象名.iloc[行索引][列索引] #行索引在前,列索引在后 In: df.loc['2024-01']['平安科技'] Out: 45.2 --- slide32.xml --- 4.2.1 使用选择器和快速访问器 3. 切 片 实例演示 使用选择器loc按行对数据框切片 按行索引切片 In: df.loc['2024-01':'2024-02'] Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 #切片结果包含结束标签 In: df.iloc[0:2] Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-02 47.1 27.3 4.6 --- slide33.xml --- 4.2.1 使用选择器和快速访问器 3. 切 片 实例演示 同时按行索引、列索引切片有几种变化的情况。 (1)行、列同时切片。 In: df.iloc[0:2,0:2] Out: 平安科技 南方通信 2024-01 45.2 31.9 2024-02 47.1 27.3 切前 2 行和前 2 列交叉处的数据块。 --- slide34.xml --- 4.2.1 使用选择器和快速访问器 3. 切 片 实例演示 同时按行索引、列索引切片有几种变化的情况。 (1)行、列同时切片。 (2)仅按列切片。 只切前面两列的数据。 In: df.iloc[:,0:2] Out: 平安科技 南方通信 2024-01 45.2 31.9 2024-02 47.1 27.3 2024-03 46.5 25.2 2024-04 49.8 24.5 --- slide35.xml --- 4.2.1 使用选择器和快速访问器 3. 切 片 实例演示 同时按行索引、列索引切片有几种变化的情况。 (1)行、列同时切片。 (2)仅按列切片。 (3)访问单个元素。 访问行、列索引分别为1、2的元素。 In: df.iloc[1,2] Out: 4.6 --- slide36.xml --- 4.2.1 使用选择器和快速访问器 3. 切 片 实例演示 同时按行索引、列索引切片有几种变化的情况。 (1)行、列同时切片。 (2)仅按列切片。 (3)访问单个元素。 快速访问器at[]和iat[]用于快速取出单个元素,功能与loc和iloc类似,但是,只访问单个元素,性能得到优化,速度更快。 at[]通过行和列的标签来获取元素。 In: df.at['2024-02','平安科技'] #行标签在前,列标签在后 Out: 47.1 iat[]通过整数位置来访问单个元素。 In: df.iat[0, 2] #行索引在前,列索引在后 Out: 3.4 --- slide37.xml --- 4.2.2 基于条件的数据筛选 1. 布尔索引 实例演示 序列和数据框都支持布尔索引,使用一个布尔值列表或序列对象来选择对应位置为True的元素,在数据框中是选择对应的行,语法格式为: 对象[[True, False,…]] #对象是序列对象,或者数据框对象,外层括号中可以是一个列表,也可以是一个序列对象,只要其中是布尔值。 In: close[[True, False, False]] Out: 平安科技 44.3 In: df[[True,False,True,False]] Out: 平安科技 南方通信 幸福银行 2024-01 45.2 31.9 3.4 2024-03 46.5 25.2 5.2 --- slide38.xml --- 4.2.2 基于条件的数据筛选 2. 关系运算 实例演示 序列对象可以进行关系运算,其结果是序列对象,元素值为布尔值。 In: close > 20 Out: 平安科技 True 南方通信 True 幸福银行 False dtype: bool --- slide39.xml --- 4.2.2 基于条件的数据筛选 2. 关系运算 实例演示 数据框选择一列后也可以进行关系运算,其结果是序列对象,元素值为布尔值。 In: df['平安科技'] > 47 Out: 2024-01 False 2024-02 True 2024-03 False 2024-04 True Name: 平安科技, dtype: bool --- slide40.xml --- 4.2.2 基于条件的数据筛选 3. 基于条件的数据筛选 实例演示 把关系运算看作一个条件,可以直接把序列和数据框关系运算和布尔索引结合起来,形成基于条件的数据筛选。 In: close[close>20] Out: 平安科技 44.3 南方通信 22.6 In: df[df['平安科技'] > 47] Out: 平安科技 南方通信 幸福银行 2024-02 47.1 27.3 4.6 2024-04 49.8 24.5 6.8 --- slide41.xml --- 4.2.3多条件联合筛选 多条件的数据筛选 实例演示 当筛选条件多于一个时,可以通过逻辑运算符 &(与)、|(或)进行组合,形成多条件联合筛选。 In: close[(close>20) & (close<40)] #每个条件都要用圆括号 Out: 南方通信 22.6 In: df[(df['平安科技'] > 47) & (df['南方通信']>26)] Out: 平安科技 南方通信 幸福银行 2024-02 47.1 27.3 4.6 --- slide42.xml --- 4.3 数据分组与聚合 4. 3.3 分组后的数据转换 4. 3.2 对分组数据进行聚合操作 4. 3.1 数据分组 --- slide43.xml --- 4.3 数据分组与聚合 根据一个或多个列的值,将数据分为若干组。然后对每组数据进行聚合操作,如汇总、统计、计算等操作。 groupby()方法 分组的列标签 功能 实现 参数 --- slide44.xml --- 示例数据 姓名 分区 一季度 二季度 三季度 四季度 0 赵四 天河 2572 3291 4388 2672 1 钱多 黄埔 2845 3161 3723 3663 2 孙冰 越秀 2100 3371 3901 3024 3 李萌 黄埔 4483 3810 1070 2312 4 周金 天河 4109 2322 3056 4066 5 吴达 天河 2435 4863 1576 1934 6 郑华 黄埔 4663 1831 1451 3456 7 王军 越秀 4839 1214 3639 2649 --- slide45.xml --- 生成示例数据 代码 In: df = DataFrame({ '姓名': ['赵四', '钱多', '孙冰', '李萌', '周金', '吴达', '郑华', '王军'], '分区': ['天河', '黄埔', '越秀', '黄埔', '天河', '天河', '黄埔', '越秀'], '一季度': [2572, 2845, 2100, 4483, 4109, 2435, 4663, 4839], '二季度': [3291, 3161, 3371, 3810, 2322, 4863, 1831, 1214], '三季度': [4388, 3723, 3901, 1070, 3056, 1576, 1451, 3639], '四季度': [2672, 3663, 3024, 2312, 4066, 1934, 3456, 2649] }) --- slide46.xml --- 4.3.1 数据分组 1. 分组 实例演示 数据分组由数据框对象的groupby()方法完成,参数为分组的列标签,生成一个分组对象,如按照“分区”分组的方法: In: group = df.groupby( '分区' ) --- slide47.xml --- 4.3.1 数据分组 2. 查看分组 实例演示 生成一个分组对象,通过该对象可以查看分组情况。 In: group.ngroups # ngroups为分组对象的属性 Out: 3 #数据框被分成了3组 从结果可以看出,所有数据按照分区被分成了3组。 --- slide48.xml --- 4.3.1 数据分组 2. 查看分组 实例演示 生成一个分组对象,通过该对象可以查看分组情况。 In: group.size() #查看各分组的数量 Out: 分区 天河 3 越秀 2 黄埔 3 --- slide49.xml --- 4.3.1 数据分组 2. 查看分组 实例演示 生成一个分组对象,通过该对象可以查看分组情况。 In: for name, g in group: #遍历各分组 print("分组名:", name) print(g) 分组名: 天河 姓名 分区 一季度 二季度 三季度 四季度 0 赵四 天河 2572 3291 4388 2672 4 周金 天河 4109 2322 3056 4066 5 吴达 天河 2435 4863 1576 1934 分组名: 越秀 姓名 分区 一季度 二季度 三季度 四季度 2 孙冰 越秀 2100 3371 3901 3024 7 王军 越秀 4839 1214 3639 2649 分组名: 黄埔 姓名 分区 一季度 二季度 三季度 四季度 1 钱多 黄埔 2845 3161 3723 3663 3 李萌 黄埔 4483 3810 1070 2312 6 郑华 黄埔 4663 1831 1451 3456 --- slide50.xml --- 4.3.2 对分组数据进行聚合操作 聚合操作可以将每个组的数据进行汇总、计算等,从而提取有用的信息。 实现:agg方法 聚合操作以及对应的函数名称为:求和(sum)、计数(count)、平均值(mean)、最大值(max)、最小值(min)等。 --- slide51.xml --- 4.3.2 对分组数据进行聚合操作 实例演示 (1)对一个列标签执行一种聚合 In: group.agg({'一季度':'sum'}) #参数是一个字典,列标签是键,操作名是值 Out: 一季度 分区 天河 9116 #结果代表天河区所有人的总和 越秀 6939 黄埔 11991 1 --- slide52.xml --- 4.3.2 对分组数据进行聚合操作 实例演示 (2)对一个列标签执行多种聚合 In: group.agg({'一季度':['sum','max']}) #参数是操作名列表 Out: 一季度 sum max 分区 天河 9116 4109 越秀 6939 4839 黄埔 11991 4663 2 --- slide53.xml --- 4.3.2 对分组数据进行聚合操作 实例演示 (3)对多个列标签执行多种聚合 In: group.agg({'一季度':['sum','max'],'二季度':['mean','min']}) #每个列标签和操作构成一个键值对 Out: 一季度 二季度 sum max mean min 分区 天河 9116 4109 3492.0 2322 越秀 6939 4839 2292.5 1214 黄埔 11991 4663 2934.0 1831 3 --- slide54.xml --- 4.3.3 分组后的数据转换 实例演示 用groupby()对数据进行分组后,还可以通过数据转换来修改或生成新的数据。 实现 transform()函数 参数 操作名字符串 功能 将操作应用到每一个分组,转换后返回返回一个序列 In: group['四季度'].transform('mean') #计算各区四季度的平均值。 Out: 0 2890.666667 #表示天河区四季度的平均值 1 3143.666667 2 2836.500000 3 3143.666667 4 2890.666667 5 2890.666667 6 3143.666667 7 2836.500000 Name: 四季度, dtype: float64 transform() 函数 “ 每个分组数据在转换后会被应用回原始 DataFrame 的相应位置 ” 意思是标签 0 、 4 、 5 对应的值为四季度天河区的平均值 --- slide55.xml --- 4.4 合并和连接 4. 4.3 数据框连接 4. 4.2合并方式 4. 4.1 数据框合并 --- slide56.xml --- 4.4.1 数据框合并 实例演示 merge()用来合并两个数据框。参数 on 指定合并关键字。 In: yu = pd.DataFrame({'学号': ['201', '202', '203'], '语文': [91, 82, 93]}) shu = pd.DataFrame({'学号': ['203', '202', '201'], '数学': [94, 85, 96]}) cheng = pd.merge(yu, shu, on='学号') cheng Out: 学号 语文 数学 0 201 91 96 1 202 82 85 2 203 93 94 merge() 方法 merge() 函数将两个数据框 yu 和 shu 按照 学号 列进行 合并,生成一个新的数据框。 数据框 yu 和 shu 中,学号列的顺序可以不同, pandas 能够自动对齐。 --- slide57.xml --- 4.4.2合并方式 实例演示 merge()方法用来将两个数据框合并成一个。使用merge()合并时,它的一个重要参数是how,它决定了数据框合并的类型。 1. 内连接 内连接只保留两个数据框中共同键值的行。也就是说,只有当两个数据框的键值匹配时,才会在结果中显示这行数据。how的值为inner,这也是默认值。 In: yu = pd.DataFrame({'学号': ['201', '202', '203'], '语文': [91, 82, 93]}) shu = pd.DataFrame({'学号': ['204', '202', '201'], '数学': [94, 85, 96]}) cheng = pd.merge(yu, shu, on='学号', how='inner') cheng Out: 学号 语文 数学 0 201 91 96 1 202 82 85 1. 内连接 只有两个数据框中都出现的学号201和202才出现在合并后的数据框中。 --- slide58.xml --- 4.4.2合并方式 实例演示 2. 左连接 左连接保留左侧数据框中的所有行,右侧数据框只有与左侧匹配的行会出现在结果中。如果没有匹配,则右侧的数据用NaN填充。how的值为left。 In: cheng = pd.merge(yu, shu, on='学号', how='left') cheng Out: 学号 语文 数学 0 201 91 96.0 1 202 82 85.0 2 203 93 NaN 2. 左连接 保留数据框yu中的所有行,203号没有数学成绩,用NaN填充。 --- slide59.xml --- 4.4.2合并方式 实例演示 3. 右连接 右连接与左连接相反,它保留右侧数据框的所有行,左侧数据框只有匹配的行会出现在结果中。如果没有匹配,则左侧的数据用NaN填充。how的值为right。 In: cheng = pd.merge(yu, shu, on='学号', how='right') cheng Out: 学号 语文 数学 0 204 NaN 94 1 202 82.0 85 2 201 91.0 96 3. 右连接 保留数据框shu中的所有行,204号没有语文成绩,用NaN填充。 --- slide60.xml --- 4.4.2合并方式 实例演示 4. 外连接 外连接保留两个数据框中的所有行,缺少匹配的数据会用NaN填充。这种方式合并所有键的值,不管是否匹配。how的值为outer。 In: cheng = pd.merge(yu, shu, on='学号', how='outer') cheng Out: 学号 语文 数学 0 201 91.0 96.0 1 202 82.0 85.0 2 203 93.0 NaN 3 204 NaN 94.0 4. 外连接 203号没有数学成绩,204号没有语文成绩,均以NaN填充。 --- slide61.xml --- 4.4.3 数据框连接 实例演示 concat() 方法 用于连接多个数据框。例如,数据框df1表示一个班的部分同学的语文和数学成绩,df2表示另一部分同学的成绩,现在需要将它们连接成一个数据框。 参数ignore_index=True用于重建索引。 In: df1 = pd.DataFrame({'学号': ['201', '202', '203'], '语文': [91, 82, 93],'数学': [94, 85, 96]}) df2 = pd.DataFrame({'学号': ['204', '205', '206'], '语文': [95, 87, 83],'数学': [84, 75, 91]}) cheng = pd.concat([df1, df2] , ignore_index=True) cheng Out: 学号 语文 数学 0 201 91 94 1 202 82 85 2 203 93 96 3 204 95 84 4 205 87 75 5 206 83 91 concat() 方法 --- slide62.xml --- 4.5 数据读取和存储 4. 5.2 读写Excel文件 4. 5.1 读写CSV文件 --- slide63.xml --- 4.5.1 读写CSV文件 实例演示 CSV(Comma-Separated Values,逗号分隔值)是一种常见的用于存储表格数据的纯文本格式。 使用to_csv()和read_csv()函数可以实现CSV文件的存取。 to_csv()是数据框的成员,要通过数据框对象调用。 In: data = [[800, 750, 500], [700, 800, 600], [680, 720, 580]] col=['会计', '保险', '外语'] ind=['2022','2023','2024'] df = DataFrame(data, columns=col, index=ind) df.to_csv('renshu.csv', index=True) 1. to_csv() 方法 --- slide64.xml --- 4.5.1 读写CSV文件 实例演示 CSV(Comma-Separated Values,逗号分隔值)是一种常见的用于存储表格数据的纯文本格式。 使用to_csv()和read_csv()函数可以实现CSV文件的存取。 to_csv()是数据框的成员,要通过数据框对象调用。 1. to_csv() 方法 index= True 指示保存索引,renshu.csv文件 内容显示如下 ,会计,保险,外语 2022,800,750,500 2023,700,800,600 2024,680,720,580 index=False指示不保存索引 ,则renshu.csv文件内容更改 为如下 会计,保险,外语 800,750,500 700,800,600 680,720,5800 --- slide65.xml --- 4.5.1 读写CSV文件 实例演示 CSV文件默认时用逗号分隔数据,也可以用sep参数指定其他的分隔符。 1. to_csv() 方法 In: df.to_csv('renshu.csv', index=True, sep='\t') sep='\t'指示用制表符作为数据分隔符 ,renshu.csv文件内容如下 会计 保险 外语 2022 800 750 500 2023 700 800 600 2024 680 720 580 --- slide66.xml --- 4.5.1 读写CSV文件 实例演示 read_csv()是pandas的成员,要通过pandas调用。read_csv()函数可以将CSV文件读取为DataFrame对象。 Pandas默认使用UTF-8编码。如果文件是用pandas的to_csv写的,则用read_csv读取的时候不用指定编码。如果文件是别的方式创建的,则用read_csv读取的时候需要指定创建时的编码,否则会出现中文乱码。 2. read_csv 方法 In: df = pd.read_csv('renshu.csv', index_col=0, sep='\t') 根据文件内容设置参数index_col和sep,如果文件第一列是索引,则设置参数index_col,否则不设置。根据文件的分隔符设置参数sep。 --- slide67.xml --- 4.5.2 读写Excel文件 实例演示 to_excel()和read_excel()函数实现Excel文件的存取。to_excel()是数据框的成员,要通过数据框对象调用。 1. to_excel() 方法 In: df.to_excel('renshu.xlsx', index=True) 参数index=True指定需要保存索引。如果不需要保存索引,则设置index=False。保存结果如图4-1所示。 --- slide68.xml --- 4.5.2 读写Excel文件 实例演示 函数to_excel保存的默认工作表的名称是Sheet1,可以通过设置参数sheet_name来指定工作表的名称。 1. to_excel() 方法 In: df.to_excel('renshu.xlsx', sheet_name='学院', index=True) --- slide69.xml --- 4.5.2 读写Excel文件 实例演示 通过函数to_excel()保存的excel工作簿中只有一个工作表。如果要在一个工作簿中保存多个工作表,则要利用pandas的ExcelWriter对象。 1. to_excel() 方法 from pandas import ExcelWriter with ExcelWriter('workbook.xlsx') as writer: df1.to_excel(writer, sheet_name='表1') df1.to_excel(writer, sheet_name='表2') 如要将两个数据框对象 d f1 和 df 2 写入一个工作簿 workbook.xlsx ,工作表名分别时表 1 和表 2 ,则示例代码如下 --- slide70.xml --- 4.5.2 读写Excel文件 实例演示 read_excel()是pandas的成员,要通过pandas调用。read_excel()用于读取Excel文件。 参数sheet_name用于指定工作表名称,如果读取工作簿的第一个工作表,也可以不设置该参数。如果工作表包含索引,则设置参数index_col,否则不设置该参数。 2. read_excel 方法 In: df = pd.read_excel('renshu.xlsx', sheet_name='学院', index_col=0) --- slide71.xml --- 4.6 数据清洗和预处理 4. 6.1 缺失值检测与处理 4. 6.2 异常值检测与处理 4. 6.3 重复值检测与处理 4. 6.4 数据类型转换 --- slide72.xml --- 4.6.1 缺失值检测与处理 实例演示 isna()或isnull()方法用来检测缺失值,返回一个布尔型的DataFrame,标识数据中哪些位置有缺失值。 1. 检测缺失值 In: a = np.array([[163, 113, 158], [np.nan, np.nan, 119], [193, 127, np.nan], [109, 126, 110]]) df = DataFrame(a, index=['一月','二月','三月','四月'], columns=['美好集团','北方通信','广东科技']) df.isna() #df.isnull()两个函数的输出结果相同 Out: 美好集团 北方通信 广东科技 一月 False False False 二月 True True False 三月 False False True 四月 False False False True 对应的位置有缺失值 --- slide73.xml --- 4.6.1 缺失值检测与处理 实例演示 处理缺失值的方式取决于数据分析的需求。常用的方法包括 使用dropna()删除包含缺失值的行或列 2. 处理 缺失值 In: df.dropna() #删除有缺失值的行,并返回一个新数据框 Out: 美好集团 北方通信 广东科技 一月 163.0 113.0 158.0 四月 109.0 126.0 110.0 --- slide74.xml --- 4.6.1 缺失值检测与处理 实例演示 处理缺失值的方式取决于数据分析的需求。常用的方法包括 fillna()用特定值(如均值、中位数或前后值)填充缺失值 2. 处理 缺失值 In: df.fillna(0) Out: 美好集团 北方通信 广东科技 一月 163.0 113.0 158.0 二月 0.0 0.0 119.0 三月 193.0 127.0 0.0 四月 109.0 126.0 110.0 用 0 值填充缺失值。 --- slide75.xml --- 4.6.1 缺失值检测与处理 实例演示 处理缺失值的方式取决于数据分析的需求。常用的方法包括 fillna()用特定值(如均值、中位数或前后值)填充缺失值 2. 处理 缺失值 In: df.fillna(method='ffill') Out: 美好集团 北方通信 广东科技 一月 163.0 113.0 158.0 二月 163.0 113.0 119.0 三月 193.0 127.0 119.0 四月 109.0 126.0 110.0 用缺失值前面的值填充。 参数method='bfill'指定用后面的值填充缺失值。 --- slide76.xml --- 4.6.1 缺失值检测与处理 实例演示 处理缺失值的方式取决于数据分析的需求。常用的方法包括 fillna()用特定值(如均值、中位数或前后值)填充缺失值 2. 处理 缺失值 In: df.fillna(value=df.mean()) Out: 美好集团 北方通信 广东科技 一月 163.0 113.0 158.0 二月 155.0 122.0 119.0 三月 193.0 127.0 129.0 四月 109.0 126.0 110.0 用所在列的平均值填充缺失值。 --- slide77.xml --- 4.6.2 异常值检测与处理 2. quantile()函数 异常值是指数据中偏离正常范围的极端值,可能是由于测量错误、数据录入错误或其他原因导致的。这些异常值如果不加以处理,可能会影响计算的准确性和分析结果。 1. 异常值及其计算 第一分位数 Q1 第三分位数 Q3 IQR = Q3 - Q1 异常值 小于 Q1 - 1.5 * IQR 或大于 Q3 + 1.5 * IQR quantile()函数用于计算数据的分位数。分位数是将数据按指定百分比划分的值,用于分析数据的分布情况。通过quantile()函数,可以计算出25%、75% 等常用的分位数。25%和75% 分位数分别称为第一和第三四分位数。 第一分位数 Q1 第三分位数 Q3 --- slide78.xml --- 实例 演示 data = pd.Series([10, 12, 15, 20, 100, 25, 30, 200]) # 1. 计算四分位数范围 (IQR) Q1 = data.quantile(0.25) Q3 = data.quantile(0.75) IQR = Q3 - Q1 # 2. 识别异常值 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers = (data < lower_bound) | (data > upper_bound) # 3. 计算均值(不包含异常值) mean_value = data[~outliers].mean() # 4. 用均值替换异常值 data[outliers] = mean_value print("处理后的数据:") print(data) 【例4-1】编写程序识别序列对象的异常值,并用均值替代异常值。 --- slide79.xml --- 4.6.3 重复值检测与处理 重复值检测与处理是数据清洗的一个重要步骤。通过检测并处理数据中的重复值,可以保证数据的完整性和准确性,避免冗余数据影响分析结果。 duplicated()函数用于检测数据中的重复值。该函数会返回一个布尔类型的序列对象,指示每一行是否为重复行。通常情况下,保留第一次出现的值,后续重复的值会标记为True。 1. 检测重复值 实例演示 In: data = {'A': [1, 2, 2, 3], 'B': [4, 5, 5, 6]} df = DataFrame(data) df.duplicated() Out: 0 False 1 False 2 True #这一行被标记为重复行 3 False --- slide80.xml --- 4.6.3 重复值检测与处理 drop_duplicates() 函数用于删除重复值。可选择保留第一行或最后一行。 2. 删除重复值 实例演示 In: df.drop_duplicates(keep='first') Out: A B 0 1 4 1 2 5 #保留第一行,重复行数据相同,序号不同 3 3 6 In: df.drop_duplicates(keep='last') Out: A B 0 1 4 2 2 5 #保留最后一行 3 3 6 --- slide81.xml --- 4.6.4 数据类型转换 因为不同的分析方法需要特定的数据类型,数据类型转换是处理和清洗数据的常见操作。 通常采用astype()方法,可以将序列、数据框指定列转或者数据框对象换为指定的数据类型。 astype()方法转换数据类型 实例演示 In: a = np.array([[163, 113, 132], [175, 129, 119], [193, 127, 125], [189, 126, 110]]) df = DataFrame(a, index=['一月','二月','三月','四月'], columns=['美好集团','北方通信','广东科技']) 将数据框的所有列都转换成目标数据类型。 In: df.astype('float32') Out: 美好集团 北方通信 广东科技 一月 163.0 113.0 132.0 二月 175.0 129.0 119.0 三月 193.0 127.0 125.0 四月 189.0 126.0 110.0 --- slide82.xml --- 4.6.4 数据类型转换 因为不同的分析方法需要特定的数据类型,数据类型转换是处理和清洗数据的常见操作。 通常采用astype()方法,可以将序列、数据框指定列转或者数据框对象换为指定的数据类型。 astype()方法转换数据类型 实例演示 只转换数据框的一列,生成一个新的序列对象。 In: df['北方通信'].astype('float32') Out: 一月 113.0 二月 129.0 三月 127.0 四月 126.0 Name: 北方通信, dtype: float32 以下命令可以将新生成的对象写入原始对象。 In: df['北方通信'] = df['北方通信'].astype('float32') --- slide83.xml --- 4.7 时间序列处理 时间序列数据是指按时间顺序排列的数据,通常用于表示金融市场数据、传感器数据、气象数据等。数据框常以时间作为行标签保存时间序列数据。 --- slide84.xml --- 4.7 时间序列处理 时间序列生成与索引设置 4.7.1 时间序列数据分析 4.7.5 时间间隔计算与转换 4.7.2 移动窗口计算 4.7.4 时间序列数据重采样 4.7.3 --- slide85.xml --- 4.7.1 时间序列生成与索引设置 date_range()函数可以快速生成规则的时间序列。例如,可以生成按天、按月、按年等递增的时间序列。参数start指定起始日期,periods指定周期数,freq指定频率,D、M、Y分别表示天、月、年。 1. date_range()函数 实例演示 In: dates = pd.date_range(start='2024-01-01', periods=10, freq='D') dates Out: DatetimeIndex(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-06', '2024-01-07', '2024-01-08', '2024-01-09', '2024-01-10'], dtype='datetime64[ns]', freq='D') 以下代码可以生成 1 0 天的日期序列。 --- slide86.xml --- 4.7.1 时间序列生成与索引设置 date_range()函数可以快速生成规则的时间序列。例如,可以生成按天、按月、按年等递增的时间序列。参数start指定起始日期,periods指定周期数,freq指定频率,D、M、Y分别表示天、月、年。 1. date_range()函数 实例演示 In: dates = pd.date_range(start='2024-01-01', periods=10, freq='M') dates Out: DatetimeIndex(['2024-01-31', '2024-02-29', '2024-03-31', '2024-04-30', '2024-05-31', '2024-06-30', '2024-07-31', '2024-08-31', '2024-09-30', '2024-10-31'], dtype='datetime64[ns]', freq='M') 以下代码可以生成10月的日期序列,每个日期对齐到月末日期。 --- slide87.xml --- 4.7.1 时间序列生成与索引设置 date_range()函数生成的对象是一个可迭代对象,可以通过索引访问其中的每一个元素,元素是一个Timestamp对象。 2. 访问 Timestamp对象 实例演示 In: dates[0] Out: Timestamp('2024-01-31 00:00:00', freq='M') --- slide88.xml --- 4.7.1 时间序列生成与索引设置 在时间序列处理中,通常将日期或时间列设置为索引,以便更好地操作、查询、切片时间序列数据。 如果数据中有日期时间列,但是以字符串的形式存储,首先可以使用pd.to_datetime()函数将其转换为datetime格式,然后通过set_index()设置该列为索引。 3. 将日期或时间列设置为索引 实例演示 In: date = ['2024-8-1','2024-8-2','2024-8-3','2024-8-4','2024-8-5','2024-8-6','2024-8-7','2024-8-8','2024-8-9','2024-8-10'] num = np.random.randint(50,100,size=(10)) df = DataFrame({'日期':date, '数量':num}) df Out: 日期 数量 0 2024-8-1 81 #数据框中有字符串形式的日期数据 1 2024-8-2 73 2 2024-8-3 62 3 2024-8-4 50 4 2024-8-5 80 5 2024-8-6 99 6 2024-8-7 89 7 2024-8-8 54 8 2024-8-9 63 9 2024-8-10 78 --- slide89.xml --- 4.7.1 时间序列生成与索引设置 在时间序列处理中,通常将日期或时间列设置为索引,以便更好地操作、查询、切片时间序列数据。 如果数据中有日期时间列,但是以字符串的形式存储,首先可以使用pd.to_datetime()函数将其转换为datetime格式,然后通过set_index()设置该列为索引。 3. 将日期或时间列设置为索引 实例演示 In: df['日期'] = pd.to_datetime(df['日期']) # 将 'date' 列转换为时间类型 df.set_index('日期', inplace=True) df Out: 日期 数量 2024-08-01 65 #日期数据被设置成索引列 2024-08-02 85 2024-08-03 97 2024-08-04 93 2024-08-05 84 2024-08-06 51 2024-08-07 72 2024-08-08 92 2024-08-09 80 2024-08-10 55 --- slide90.xml --- 4.7.1 时间序列生成与索引设置 可以在创建DataFrame时直接将pd.date_range()生成的日期序列作为索引。 3. 将日期或时间列设置为索引 实例演示 In: dates = pd.date_range(start='2024-08-01', periods=10, freq='D') num = np.random.randint(50,100,size=(10)) df = pd.DataFrame(num, index=dates, columns=['数量']) df Out: 数量 2024-08-01 76 2024-08-02 85 2024-08-03 95 2024-08-04 96 2024-08-05 91 2024-08-06 83 2024-08-07 90 2024-08-08 77 2024-08-09 86 2024-08-10 60 --- slide91.xml --- 4.7.2 时间间隔计算与转换 时间间隔计算通常涉及两个时间点或两个时间序列之间的差异。pandas使用Timedelta对象来表示时间间隔。 如果有两个时间点,可以直接使用减法运算来计算它们之间的时间差,结果是一个 Timedelta对象。 1. 时间间隔计算 实例演示 In: start = pd.Timestamp('2024-08-01 08:00') end = pd.Timestamp('2024-08-31 08:00') diff = end – start type(diff) Out: pandas._libs.tslibs.timedeltas.Timedelta In: diff Out: Timedelta('30 days 00:00:00') #两个日期之间相隔30天 --- slide92.xml --- 4.7.2 时间间隔计算与转换 对于整个时间序列,也可以通过类似的减法运算计算出每个时间点之间的差异。 1. 时间间隔计算 实例演示 In: times = pd.Series(pd.date_range('2024-01-01', periods=5, freq='M')) diffs = times.diff() #diffs是一个序列,每个点与前一个的差 diffs Out: 0 NaT 1 29 days 2 31 days 3 30 days 4 31 days --- slide93.xml --- 4.7.2 时间间隔计算与转换 时间间隔可以转换为不同的时间单位,如天、小时、分钟或秒等。Timedelta对象支持直接访问特定单位的时间差。 2. 时间间隔 转换 实例演示 In: start = pd.Timestamp('2024-09-01 08:00:00') end = pd.Timestamp('2024-09-03 09:10:10') diff = end - start diff.days #获取时间差包含的天数 Out: 2 In: diff.seconds #时间差中除了天数剩余时间包含的秒数,通过计算可以得到小时数和分钟数 Out: 4210 In: diff.total_seconds() #函数调用,返回时间差包含的总秒数 Out[86]: 177010.0 --- slide94.xml --- 4.7.3时间序列数据重采样 resample用于对时间序列数据进行重采样。通过 resample,可以根据指定的时间频率对数据进行聚合、填充、插值等操作。 常用频率:如 'D'(天),'W'(周),'M'(月)等。在频率前面加上一个整数指定采样周期,如‘3D’表示每3天采样。 降采样是将高频率的时间序列数据降低到更低的频率,如将每日数据降为每周数据。 升采样是将低频率的时间序列数据提升到更高的频率,如将每月数据扩展为每日数据(通常需要插值)。 resample () 方法 实例演示 In: # 创建时间序列数据 dates = pd.date_range('2024-01-01', periods=14, freq='D') df = pd.DataFrame({'温度': [30, 32, 31, 29, 28, 27, 26, 25, 24, 23, 31, 29, 28, 27]}, index=dates) # 按周进行重采样,取最大值 weekly_max_temp = df.resample('W').max() weekly_max_temp Out: 温度 2024-01-07 32 #每7天统计一次最高温度 2024-01-14 31 --- slide95.xml --- 4.7.4 移动窗口计算 rolling()方法用于对时间序列或任意连续数据进行移动窗口计算。它允许在指定的窗口大小内对数据进行统计操作(如求和、平均值、最大值、最小值等),通常用于时间序列分析中的平滑处理、趋势分析或噪声过滤。参数window指定滚动窗口的大小,即每次计算时包含的连续数据点个数。 rolling()方法 实例演示 In: dates = pd.date_range('2024-09-01', periods=7, freq='D') df = pd.DataFrame({'温度': [30, 32, 31, 29, 28, 27, 26]}, index=dates) # 计算3天的滚动平均温度 df['滚动平均'] = df['温度'].rolling(window=3).max() Out: 温度 滚动平均 2024-09-01 30 NaN 2024-09-02 32 NaN 2024-09-03 31 32.0 #最近3天的最高温度,前面2天设为空值 2024-09-04 29 32.0 2024-09-05 28 31.0 2024-09-06 27 29.0 2024-09-07 26 28.0 --- slide96.xml --- 4.7.5时间序列数据分析 时间序列数据分析是对按时间顺序排列的数据进行研究和处理的过程,旨在发现时间上的趋势、季节性变化、周期性波动等规律。时间序列分析在金融、经济、气象、制造业等领域具有广泛的应用,如股票价格波动预测、市场需求分析、气候变化趋势等。 1. 时间序列数据 分析 2. 股票KDJ指标 KDJ指标是股票技术分析中常用的一种动量指标,用于判断市场的超买或超卖状态。该指标综合了价格的波动趋势和相对位置,通过对价格的历史数据进行统计分析,生成K值、D值和J值三个曲线指标。K值和D值反映股价趋势的中短期波动,而J值则用于放大市场信号,能够更敏感地捕捉市场的转折点。通常情况下,KDJ指标可以帮助投资者判断买入或卖出时机,当指标处于极端区域时,往往意味着趋势可能反转。 --- slide97.xml --- 4.7.5时间序列数据分析 首先要计算周期n日的RSV值,然后再计算K值、D值、J值。 当日RSV=(Cn-Ln)÷(Hn-Ln)×100 式中,Cn为第n日收盘价;Ln为n日内的最低价;Hn为n日内的最高价。 其次,计算K值与D值: 当日K值=2/3×前一日K值+1/3×当日RSV 当日D值=2/3×前一日D值+1/3×当日K值 若无前一日K 值与D值,则可分别用50来代替。 当日J值=3×当日K值 – 2×当日D值 3. 股票KDJ指标 计算 实例 演示 文件“ 601398.xlsx ” 保存了幸福银行 2 024 年 1 月 2 日至 2 024 年 8 月 3 0 日的收盘、最高和最低价,部分数据如图 4- 2 所示。 --- slide98.xml --- 实例 演示 def kdj(stockData, n=9, m1=3, m2=3): # 计算 RSV low_n = stockData['最低'].rolling(window=n, min_periods=1).min() # 最近n天的最低价 high_n = stockData['最高'].rolling(window=n, min_periods=1).max() # 最近n天的最高价 rsv = (stockData['收盘'] - low_n) / (high_n - low_n) * 100 现以该数据为例编写计算KDJ指标的程序。程序如下: rolling 函数用于创建一个滚动窗口对象,可以对数据进行移动计算或滑动操作。通过指定窗口大小(如时间窗或固定数目的观测值), rolling 函数能够对数据的每个子集执行聚合操作,如求和、均值、标准差等。常用的参数包括窗口大小 window ,以及是否包含当前行的数据 min_periods 。 --- slide99.xml --- 实例 演示 # 初始化 K、D 列 stockData['K'] = np.nan stockData['D'] = np.nan # 初始值 K 和 D K_last = 50 D_last = 50 # 计算 K 和 D for i in range(len(stockData)): K_last = (2/3) * K_last + (1/3) * rsv.iloc[i] #计算K值 D_last = (2/3) * D_last + (1/3) * K_last #计算D值 stockData.at[stockData.index[i], 'K'] = K_last stockData.at[stockData.index[i], 'D'] = D_last 现以该数据为例编写计算KDJ指标的程序。程序如下: --- slide100.xml --- 实例 演示 # 计算 J 值 stockData['J'] = 3 * stockData['K'] - 2 * stockData['D'] return stockData = pd.read_excel('601398.xlsx', index_col=0) kdj(stockData) print(stockData[['K','D','J']]) 现以该数据为例编写计算KDJ指标的程序。程序如下: 程序部分计算结果如图 4- 3 所示。