本章将介绍Pandas对数据的基础操作,包括索引的创建和使用、数据信息的查看、数据的筛选、数据的统计、数据类型的转换、排序、添加修改、添加修改数据、使用函数等内容。这些是最为常见的操作,几乎所有数据分析工作都会涉及。
4.1 索引操作
建立索引可以在数据读取加载中指定索引:
data = 'https://www.gairuo.com/file/data/dataset/team.xlsx'
df = pd.read_excel(data, index_col='name') # 将索引设置为name
df
'''
team Q1 Q2 Q3 Q4
name
Liver E 89 21 24 64
Arry C 36 37 37 57
Ack A 57 60 18 84
Eorge C 93 96 71 78
Oah D 65 49 61 86
...
'''
我们发现name成为了索引,在显示时已经不与其他列名在一行了,而是自己单独占有一行。如果加载时没有指定索引,我们可以使用df.set_index()指定:
df = pd.read_excel(data) # 读取数据不设索引
df.set_index('name') # 设置索引
如果需要,我们还可以设置两层索引:
df.set_index(['name', 'team']) # 设置两层索引
df.set_index([df.name.str[0],'name']) # 将姓名的第一个字母和姓名设置为索引
需要注意的是,在以上操作中,我们并没有修改原来的df变量中的内容,如果希望用设置索引后的数据替换原来df变量中的数据,可以直接进行赋值操作或者传入inplace参数:
df = df.set_index('name') # 建立索引并重写覆盖df
df.set_index('name', inplace=True) # 同上,使索引生效
可以将一个Series指定为索引:
s = pd.Series([i for i in range(100)])
df.set_index(s) # 指定一个索引
df.set_index([s, 'name']) # 同时指定索引和现有字段
df.set_index([s, s**2]) # 计算索引
以下为其他两个常用的操作:
df.set_index('month', drop=False) # 保留原列
df.set_index('month', append=True) # 保留原来的索引
有时我们想取消已有的索引,可以使用df.reset_index(),它的操作与set_index相反。以下是一些常用的操作:
df.reset_index() # 清除索引
df.set_index('month').reset_index() # 相当于什么也没做
删除原索引,month列没了
df.set_index('month').reset_index(drop=True)
df2.reset_index(inplace=True) # 覆盖使生效
year一级索引取消
df.set_index(['month', 'year']).reset_index(level=1)
df2.reset_index(level='class') # 同上,使用层级索引名
df.reset_index(level='class', col_level=1) # 列索引
不存在层级名称的填入指定名称
df.reset_index(level='class', col_level=1, col_fill='species')
为了适应各种业务数据的处理,索引又针对各种类型数据定义了不同的索引类型。
数字索引(NumericIndex)共有以下几种。
RangeIndex:单调整数范围的不可变索引。
Int64Index:64位整型索引。
UInt64Index:无符号整数索引。
Float64Index:64位浮点型索引。
示例如下:
pd.RangeIndex(1,100,2)
RangeIndex(start=1, stop=100, step=2)
pd.Int64Index([1,2,3,-4], name='num')
Int64Index([1, 2, 3, -4], dtype='int64', name='num')
pd.UInt64Index([1,2,3,4])
UInt64Index([1, 2, 3, 4], dtype='uint64')
pd.Float64Index([1.2,2.3,3,4])
Float64Index([1.2, 2.3, 3.0, 4.0], dtype='float64')
类别索引(CategoricalIndex):类别只能包含有限数量的(通常是固定的)可能值(类别)。可以理解成枚举,比如性别只有男女,但在数据中每行都有,如果按文本处理会效率不高。类别的底层是pandas.Categorical。类别在第12章会专门讲解,只有在体量非常大的数据面前才能显示其优势。
pd.CategoricalIndex(['a', 'b', 'a', 'b'])
CategoricalIndex(['a', 'b', 'a', 'b'], categories=['a', 'b'], ordered=False,
dtype='category')
间隔索引(IntervalIndex)代表每个数据的数值或者时间区间,一般应用于分箱数据。
pd.interval_range(start=0, end=5)
'''
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
closed='right',
dtype='interval[int64]')
'''
多层索引(MultiIndex):多个层次且有归属关系的索引。
arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))
'''
MultiIndex([(1, 'red'),
(1, 'blue'),
(2, 'red'),
(2, 'blue')],
names=['number', 'color'])
'''
时间索引(DatetimeIndex):时序数据的时间。
从一个日期连续到另一个日期
pd.date_range(start='1/1/2018', end='1/08/2018')
指定开始时间和周期
pd.date_range(start='1/1/2018', periods=8)
以月为周期
pd.period_range(start='2017-01-01', end='2018-01-01', freq='M')
周期嵌套
pd.period_range(start=pd.Period('2017Q1', freq='Q'),
end=pd.Period('2017Q2', freq='Q'), freq='M')
时间差索引(TimedeltaIndex):代表时间长度的数据。
pd.TimedeltaIndex(data =['06:05:01.000030', '+23:59:59.999999',
'22 day 2 min 3us 10ns', '+23:29:59.999999',
'+12:19:59.999999'])
使用datetime
pd.TimedeltaIndex(['1 days', '1 days, 00:00:05',
np.timedelta64(2, 'D'),
datetime.timedelta(days=2, seconds=2)])
周期索引(PeriodIndex):一定频度的时间。
t = pd.period_range('2020-5-1 10:00:05', periods=8, freq='S')
pd.PeriodIndex(t,freq='S')
行和列的索引在Pandas里其实是一个Index对象,以下是创建一个Index对象的方法:
pd.Index([1, 2, 3])
Int64Index([1, 2, 3], dtype='int64')
pd.Index(list('abc'))
Index(['a', 'b', 'c'], dtype='object')
可以用name指定一个索引名称
pd.Index(['e', 'd', 'a', 'b'], name='something')
索引对象可以传入构建数据和读取数据的操作中。可以查看索引对象,列和行方向的索引对象如下:
df.index
RangeIndex(start=0, stop=4, step=1)
df.columns
Index(['month', 'year', 'sale'], dtype='object')
可以通过以下一系列操作查询索引的相关属性,以下方法也适用于df.columns,因为它们都是index对象。
常用属性
df.index.name # 名称
df.index.array # array数组
df.index.dtype # 数据类型
df.index.shape # 形状
df.index.size # 元素数量
df.index.values # array数组
其他,不常用
df.index.empty # 是否为空
df.index.is_unique # 是否不重复
df.index.names # 名称列表
df.index.is_all_dates # 是否全是日期时间
df.index.has_duplicates # 是否有重复值
df.index.values # 索引的值array
以下是索引的常用操作,这些操作会在我们今后处理数据中发挥作用。以下方法也适用于df.columns,因为都是index对象。
常用方法
df.index.astype('int64') # 转换类型
df.index.isin() # 是否存在,见下方示例
df.index.rename('number') # 修改索引名称
df.index.nunique() # 不重复值的数量
df.index.sort_values(ascending=False,) # 排序,倒序
df.index.map(lambda x:x+'_') # map函数处理
df.index.str.replace('_', '') # str替换
df.index.str.split('_') # 分隔
df.index.to_list() # 转为列表
df.index.to_frame(index=False, name='a') # 转成DataFrame
df.index.to_series() # 转为series
df.index.to_numpy() # 转为numpy
df.index.unique() # 去重
df.index.value_counts() # 去重及计数
df.index.where(df.index=='a') # 筛选
df.index.rename('grade', inplace=False) # 重命名索引
df.index.rename(['species', 'year']) # 多层,重命名索引
df.index.max() # 最大值
df.index.argmax() # 最大索引值
df.index.any()
df.index.all()
df.index.T # 转置,在多层索引里很有用
以下是一些不常用但很重要的操作:
其他,不常用
df.index.append(pd.Index([4,5])) # 追加
df.index.repeat(2) # 重复几次
df.index.inferred_type # 推测数据类型
df.index.hasnans # 有没有空值
df.index.is_monotonic_decreasing # 是否单调递减
df.index.is_monotonic # 是否有单调性
df.index.is_monotonic_increasing # 是否单调递增
df.index.nbytes # 基础数据中的字节数
df.index.ndim # 维度数,维数
df.index.nlevels # 索引层级数,通常为1
df.index.min() # 最小值
df.index.argmin() # 最小索引值
df.index.argsort() # 顺序值组成的数组
df.index.asof(2) # 返回最近的索引
索引类型转换
df.index.astype('int64', copy=True) # 深拷贝
拷贝
df.index.copy(name='new', deep=True, dtype='int64')
df.index.delete(1) # 删除指定位置
对比不同
df.index.difference(pd.Index([1,2,4]), sort=False)
df.index.drop('a', errors='ignore') # 删除
df.index.drop_duplicates(keep='first') # 去重值
df.index.droplevel(0) # 删除层级
df.index.dropna(how='all') # 删除空值
df.index.duplicated(keep='first') # 重复值在结果数组中为True
df.index.equals(df.index) # 与另一个索引对象是否相同
df.index.factorize() # 分解成(array:0-n, Index)
df.index.fillna(0, {0:'nan'}) # 填充空值
字符列表,把name值加在第一位,每个值加10
df.index.format(name=True, formatter=lambda x:x+10)
返回一个array,指定值的索引位数组,不在的为-1
df.index.get_indexer([2,9])
获取指定层级Index对象
df.index.get_level_values(0)
指定索引的位置,见示例
df.index.get_loc('b')
df.index.insert(2, 'f') # 在索引位2插入f
df.index.intersection(df.index) # 交集
df.index.is_(df.index) # 类似is检查
df.index.is_categorical() # 是否分类数据
df.index.is_type_compatible(df.index) # 类型是否兼容
df.index.is_type_compatible(1) # 类型是否兼容
df.index.isna() # array是否为空
df.index.isnull() # array是否缺失值
df.index.join(df.index, how='left') # 连接
df.index.notna() # 是否不存在的值
df.index.notnull() # 是否不存在的值
df.index.ravel() # 展平值的ndarray
df.index.reindex(['a','b']) # 新索引 (Index,array:0-n)
df.index.searchsorted('f') # 如果插入这个值,排序后在哪个索引位
df.index.searchsorted([0, 4]) # array([0, 3]) 多个
df.index.set_names('quarter') # 设置索引名称
df.index.set_names('species', level=0)
df.index.set_names(['kind', 'year'], inplace=True)
df.index.shift(10, freq='D') # 日期索引向前移动10天
idx1.symmetric_difference(idx2) # 两个索引不同的内容
idx1.union(idx2) # 拼接
df.add_prefix('t_') # 表头加前缀
df.add_suffix('_d') # 表头加后缀
df.first_valid_index() # 第一个有值的索引
df.last_valid_index() # 最后一个有值的索引
将一个数据列置为索引后,就不能再像修改列名那样修改索引的名称了,需要使用df.rename_axis方法。它不仅可以修改索引名,还可以修改列名。需要注意的是,这里修改的是索引名称,不是索引或者列名本身。
s.rename_axis("student_name") # 索引重命名
df.rename_axis(["dow", "hr"]) # 多层索引修改索引名
df.rename_axis('info', axis="columns") # 修改行索引名
修改多层列索引名
df.rename_axis(index={'a': 'A', 'b': 'B'})
修改多层列索引名
df.rename_axis(columns={'name': 's_name', 'b': 'B'})
df.rename_axis(columns=str.upper) # 行索引名变大写
用来修改行和列的索引名的主要函数是df.rename和df.set_axis。df.rename可以给定一个字典,键是原名称,值是想要修改的名称,还可以传入一个与原索引等长度序列进行覆盖修改,用一个函数处理原索引名。以下是一些具体的使用方法举例:
一一对应修改列索引
df.rename(columns={"A": "a", "B": "c"})
df.rename(str.lower, axis='columns')
修改行索引
df.rename(index={0: "x", 1: "y", 2: "z"})
df.rename({1: 2, 2: 4}, axis='index')
修改数据类型
df.rename(index=str)
重新修改索引
replacements = {l1:l2 for l1, l2 in zip(list1, list2)}
df.rename(replacements)
列名加前缀
df.rename(lambda x:'t_' + x, axis=1)
利用iter()函数的next特性修改
df.rename(lambda x, y=iter('abcdef'): next(y), axis=1)
修改列名,用解包形式生成新旧字段字典
df.rename(columns=dict(zip(df, list('abcd'))))
df.set_axis可以将所需的索引分配给给定的轴,通过分配类似列表或索引的方式来更改列标签或行标签的索引。
修改索引
df.set_axis(['a', 'b', 'c'], axis='index')
修改列名
df.set_axis(list('abcd'), axis=1)
使修改生效
df.set_axis(['a', 'b'], axis='columns', inplace=True)
传入索引内容
df.set_axis(pd.Index(list('abcde')), axis=0)
4.2 数据的信息
本节主要介绍DataFrame的基础信息和统计性信息。在我们拿到一个数据集,用Pandas载入后,需要做一些初步的验证,比如行名、列名是否一致,数据量是否有缺失,各列的数据类型等,让我们对数据的全貌有所了解。本节介绍的大多数功能对Series也是适用的。
df.head():前部数据,默认5条,可指定条数。
df.tail():尾部数据,默认5条,可指定条数。
df.sample():一条随机数据,可指定条数。
df = pd.read_excel('https://www.gairuo.com/file/data/dataset/team.xlsx')
s = df.Q1 # 取其中一列,形成Series
df.head() # 查看前5条数据
'''
name team Q1 Q2 Q3 Q4
0 Liver E 89 21 24 64
1 Arry C 36 37 37 57
2 Ack A 57 60 18 84
3 Eorge C 93 96 71 78
4 Oah D 65 49 61 86
'''
其他方法的使用如下:
df.head(10) # 查看前10条数据
s.tail() # 查看后5条数据
df.tail(10) # 查看后10条数据
df.sample() # 随机查看一条数据
s.sample(3) # 随机查看3条数据
执行df.shape会返回一个元组,该元组的第一个元素代表行数,第二个元素代表列数,这就是这个数据的基本形状,也是数据的大小。
df.shape
(100, 6)
共100行6列(索引不算)
Series 只有一个值
s.shape
(100,)
执行df.info会显示所有数据的类型、索引情况、行列数、各字段数据类型、内存占用等。Series不支持。
`python
df.info
”’
RangeIndex: 100 entries, 0 to 99
Data columns (total 6 columns):
# Column Non-Null Count Dtype
Original: https://blog.csdn.net/weixin_46249441/article/details/127124314
Author: 时宜_
Title: 【Pandas 数据分析 4-1】Pandas基础操作
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/740768/
转载文章受原作者版权保护。转载请注明原作者出处!