接下来进行pandas module部分的学习,和主要用于处理array和matrix的numpy module不同,pandas则主要处理series和dataframe类型的数据。
更具体地说,有以下几个数据类别:
1 series:one dimension,与numpy中的一维array以及基本python数据类型的list很像。区别是:list中的元素可以是不同的数据类型,array中的数据类型主要是numeric,series中的元素可以是不同的数据类型,并且有相应的索引。
2 time series:相应的,当索引为时间格式时,就生成了time series数据类型。
3 dataframe:表格型数据结构。很多功能与R中的data.frame类似。可以将dataframe理解为series的容器。dataframe比series用的更为频繁些,也有相应的索引。
4 panel :三维的数组,可以理解为dataframe的容器。用的比较少。
所以接下来从series和dataframe两个部分来学习pandas module。
SERIES
1 Series的创建
1 pd.Series(list,index=[ ]),
第一个参数可以是list或者array,同样也可以是dict(key作为索引),也可以是dataframe的某一行或者某一列。
第二个参数是Series中数据的索引,可以省略。
import numpy as np
import pandas as pd
print(pd.Series([1,4,'ww','tt'])) # 第一个参数为list
print(pd.Series(np.arange(10))) # 第一个参数为array
print(pd.Series(['leo','man',26],index=['name','sex','age'])) # 自己创建索引
print(pd.Series({'python':9000,'c++':9001,'c#':9000})) # 第一个参数为dictionary
a=pd.Series([1,4,'ww','tt'])
print(a.index)
print(a.values)
2 Series索引的应用
import pandas as pd
import numpy as np
### 根据索引查看值和修改值
a=pd.Series([1,4,'ww','tt'])
print(a[0])
a[0]="leo"
print(a)
### 对于dictionary来说,如果自定义了索引,自定的索引会自动寻找原来的索引,如果一样的,就取原来索引对应的值,如果没有值,都对齐赋给NaN。
b={'python':9000,'c++':9001,'c#':9000}; c=pd.Series(b,index=['java','c++','c#'])
print(c)
### output:
### java NaN
### c++ 9001.0
### c# 9000.0
### dtype: float64
######--------------------------------------------------------------------------------
### 索引的名字是可以从新定义
c.index= ['语文','数学','English']
print(c)
### output:
### 语文 NaN
### 数学 9001.0
### English 9000.0
### dtype: float64
3 Series的直方统计
pd.value_counts()
和DataFrame结合起来使用感觉特别好
import numpy as np
import pandas as pd
example=pd.Series(np.random.randint(0, 5, size=10)) ### 生成范围在[0,5]的随机int整数序列
example.value_counts() ### 对上面序列完成直方统计
4 Series的字符串处理
import numpy as np
import pandas as pd
example=pd.Series(['A','B','C','Aab','Baca',np.nan,np.nan,'CABA','dog','cat'])
example.str.lower() ### 对字符串进行全部小写处理
5 Series的shift()函数
import numpy as np
import pandas as pd
example=pd.Series([1,2,3,np.nan,4,5]).shift(2)
### 注意shift()的作用,shift(2)说明行往下移两个单位
### output:
### 0 NaN
### 1 NaN
### 2 1.0
### 3 2.0
### 4 3.0
### 5 NaN
### dtype: float64
6 Series的cut()和qcut()函数
cut() 函数(以值为依据实现分箱)及 qcut() 函数(以样本分位数为依据实现分箱)用于连续值的离散化,常用于连续变量的分箱操作。
import pandas as pd
factor1 = pd.cut(arr, [-5, -1, 0, 1, 5])
factor2 = pd.qcut(arr, [0, .25, .5, .75, 1])
### 定义分箱时,还可以传递无穷值。
factor3 = pd.cut(arr, [-np.inf, 0, np.inf])
10 杂七杂八的Series笔记总结
1 NumPy的mean、std、sum 等方法默认不统计 Series 里的空值。
2 Series.nunique() 返回 Series 里所有非空值的唯一值。
3 Series.astype(‘category’),将Series属性变为“category”类别
DataFrame
1 DataFrame的生成
大概来说,常用的有:1 直接生成;2 通过dictionary生成。
import numpy as np
import pandas as pd
### 直接生成
dates = pd.date_range('20200101', periods=6)
example = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
print(example)
### output:
### A B C D
### 2020-01-01 0.469112 -0.282863 -1.509059 -1.135632
### 2020-01-02 1.212112 -0.173215 0.119209 -1.044236
### 2020-01-03 -0.861849 -2.104569 -0.494929 1.071804
### 2020-01-04 0.721555 -0.706771 -1.039575 0.271860
### 2020-01-05 -0.424972 0.567020 0.276232 -1.087401
### 2020-01-06 -0.673690 0.113648 -1.478427 0.524988
### 通过dictionary生成
example = pd.DataFrame({'A': 1.,'B': pd.Timestamp('20200102'),'C': pd.Series(1, index=list(range(4)), dtype='float32'),'D': np.array([3] * 4, dtype='int32')})
print(example)
### output:
### A B C D
### 0 1.0 2020-01-01 1.0 3
### 1 1.0 2020-01-01 1.0 3
### 2 1.0 2020-01-01 1.0 3
### 3 1.0 2020-01-01 1.0 3
2 DataFrame性质展示常用函数
1 example.dtypes:查看每列的数据类型
2 example.head():默认查看前五行
3 example.tail():默认查看后五行
4 example.index:查看索引
5 example.columns:查看列名
6 example.describe():可以快速查看数据的统计摘要
7 example.T:实现DataFrame的转置
8 example.sort_index(axis=1, ascending=False):按列名进行排序
9 example.sort_values(by=“A”):按列值进行排序,如例子按A列的值进行排序
10 example.T:
3 DataFrame与Array的相互转换
NumPy 数组只有一种数据类型,DataFrame 每列的数据类型可以各不相同。当DataFrame每列的数据类型一样时,使用to_numpy()可以实现较快转换,当DataFrame 每列的数据类型各不相同时,使用to_numpy() 就会耗费较多资源。
import numpy as np
import pandas as pd
dates = pd.date_range('20200101', periods=6)
example = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
print(example.to_numpy())
### output:
### array([[ 0.4691, -0.2829, -1.5091, -1.1356],
### [ 1.2121, -0.1732, 0.1192, -1.0442],
### [-0.8618, -2.1046, -0.4949, 1.0718],
### [ 0.7216, -0.7068, -1.0396, 0.2719],
### [-0.425 , 0.567 , 0.2762, -1.0874],
### [-0.6737, 0.1136, -1.4784, 0.525 ]])
4 DataFrame的索引和数据选择
1 选择特定列:example.A or example[“A”]
2 选择特定行:example[0:3]
3 按条件筛选:example.loc[‘20200102’:‘20200104’, [‘A’, ‘B’]] (index and column names) or example.loc[:, [‘A’, ‘B’]]
4 快速访问标量:example.at[dates[0], ‘A’]
5 按特定位置筛选:example.iloc[3:5, 0:2] 行列 or example.iloc[3] 行 or df.iloc[[1, 2, 4], [0, 2]]
6 快速访问标量:example.iat[1, 1]
7 布尔索引:example[example.A > 0] 等价于 example。wher(example.A > 0);where使用可选other参数替换条件为False的值:example.where(example < 0, -example);另外,where有一个可选参数,inplace以便可以在不创建副本的情况下修改原始数据:example.where(example > 0, -example, inplace=True)。
8 isin()索引:example[example[‘E’].isin([‘two’, ‘four’])]
9 重建索引:example.reindex(index=dates[0:4], columns=list(example.columns) + [‘E’]) [reindex() 可以更改、添加、删除指定轴的索引,并返回数据副本,原数据不会被更改。]
10 索引排序:example.sort_index(),注意如果按index来进行筛选,筛选条件中有index不存在于Series或者DataFrame中,如果index是乱序的且未经过排序,输出结果会报错的。
11 .loc,.iloc以及[]索引也可以接受一个callable索引器。在callable必须与一个参数(调用系列或数据帧)返回的有效输出索引功能。example.loc[lambda df: df.A > 0, :] or example.loc[:, lambda df: [‘A’, ‘B’]]。
12 不推荐使用IX索引器。.loc,如果是想标记索引;.iloc,如果是想要定位索引。
13 选择随机样本,这个对于建模随机选择训练集和测试集特别有用,sample()方法随机选择Series或DataFrame中的行或列。
13.1 默认情况下,该方法将对行进行采样,并接受要返回的特定行数/列数或一小部分行。example.sample(n=3) or example.sample(frac=0.5)。
13.2 默认情况下,sample最多会返回每行一次,但也可以使用以下replace选项进行替换:s.sample(n=6, replace=False) or s.sample(n=6, replace=True)则会返回重复行。
13.3 非等权重取样,默认情况下,每行具有相同的选择概率,但如果希望每行具有不同的概率,则可以在sample()中加入权重参数weights。这些权重可以是list,array或series,但它们的长度必须与采样的对象的长度相同。缺失的值将被视为零的权重,并且不允许使用inf值。如果权重不总和为1,则通过将所有权重除以权重之和来进行重新赋予新的权重。
import pandas as pd
import numpy as np
example = pd.Series([0, 2, 4, 6, 8, 10])
example_weights = [0, 0, 0.2, 0.2, 0.2, 0.4]
example.sample(n=3, weights=example_weights)
### or
example.sample(n=3, weights=[0, 0, 0.2, 0.2, 0.2, 0.4])
example = pd.DataFrame({'col1': [9, 8, 7, 6],\
'weight_column': [0.5, 0.4, 0.1, 0]})
example.sample(n=3, weights='weight_column')
13.4 sample()还允许用户使用axis=0或者axis=1参数进行选择对列或是行进行采样。
13.5 sample()使用random_state参数为随机数生成器设置种子,该参数将接受整数(作为种子)或NumPy RandomState对象。sample(n=2, random_state=2)
14 query():DataFrame对象有一个query()允许使用表达式进行选择的方法。这个方法可以获取列的值,其中列b具有列值a和值之间的值c。example.query(’(a < b) & (b < c)’);另外,query()支持 Python的"in"和"not in"的比较运算符的特殊用法:df.query(‘a in b’)
15 duplicated()和drop_duplicates()。每个都将用于标识重复行的列作为参数。duplicated 返回一个布尔向量,其长度为行数,表示行是否重复;drop_duplicates 删除重复的行。
### keep参数设置:
### keep='first' (默认值):标记/删除重复项,第一次出现除外。
### keep='last':标记/删除重复项,除了最后一次出现。
### keep=False:标记/删除所有重复项。
import numpy as np; import pandas as pd
example = pd.DataFrame({'a': ['one', 'one', 'two', 'two', 'two', 'three', 'four'],\
'b': ['x', 'y', 'x', 'y', 'x', 'x', 'x'],\
'c': np.random.randn(7)})
example.duplicated('a');
### output:
### 0 False
### 1 True
### 2 False
### 3 True
### 4 True
### 5 False
### 6 False
### dtype: bool
example.duplicated('a', keep='last')
### output:
### 0 True
### 1 False
### 2 True
### 3 True
### 4 False
### 5 False
### 6 False
### dtype: bool
example.drop_duplicates('a')
example.drop_duplicates('a', keep='last')
example.drop_duplicates('a', keep=False)
example.drop_duplicates(['a', 'b'])
16 lookup():在给定一系列行标签和列标签的情况下提取一组值,并且该lookup方法允许此操作并返回NumPy数组。
example = pd.DataFrame(np.random.rand(20, 4), columns = [‘A’, ‘B’, ‘C’, ‘D’]).
lookup(list(range(0, 10, 2)), [‘B’, ‘C’, ‘A’, ‘B’, ‘D’])
return:“array([0.6052, 0.6905, 0.1032, 0.9860, 0.1982])”
5 DataFrame的赋值
1 example[“F”]=pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range(‘20200101’, periods=6))
2 按标签赋值:example.at[dates[0], ‘A’] = 0
3 按位置赋值:example.iat[0, 1] = 0
4 按 NumPy 数组赋值:example.loc[:, ‘D’] = np.array([5] * len(df))
5 用 where 条件赋值:example[example > 0] = 0
6 DataFrame的缺失值处理
6.1 Nan相关
Pandas 主要用 np.nan 表示缺失数据。 计算时,默认不包含空值。
1 example.dropna(how=“any”):删除所有含缺失值的行
2 example.fillna(value=“aa”):填充缺失值,括号当中为填充的数值
3 pd.isna(example):提取 nan 值的布尔值,true or false
4 np.nan
5 example.notna():提取 nan 值的布尔值,true(not nan) or false(nan)
6 注意:pandas/NumPy uses the fact that “np.nan != np.nan”
7 example.fillna(method=‘pad’, limit=1):
Method: pad / ffill, which is “Fill values forward”; bfill / backfill, which is “Fill values backward”.
8 example.fillna(example.mean()):均值填充null value;example.fillna(example.mean()[‘B’:‘C’]):仅B C列。
6.2 interpolate()
1 example.interpolate():插值法填充null value;"method"参数,option: “time”, “values”
“values”: For a floating-point index
“quadratic”: dealing with a time series that is growing at an increasing rate
“pchip”: have values approximating a cumulative distribution function
“akima”: fill missing values with goal of smooth plotting
in addition, “‘spline’, order=2”, “cubic”, “‘polynomial’, order=2”, “linear”.
2 example.interpolate(limit=1, limit_direction=‘backward’ or ‘both’)
6.3 replace()
可以用replace()来完成 null value的替换。
1 example.replace(0, 5)
2 example.replace([0, 1, 2, 3, 4], [4, 3, 2, 1, 0])
3 specify a mapping dict:example.replace({0: 10, 1: 100})
4 specify individual values by column:example.replace({‘a’: 0, ‘b’: 5}, 100)
5 example.replace([1, 2, 3], method=‘pad’ or ‘backfill’)
6 example.replace([r’.’, r’(a)’], [‘dot’, r’\1stuff’], regex=True)
7 example.replace(r’\s*.\s*’, np.nan, regex=True)
7 DataFrame的统计函数
7.1 mean()
1 example.mean():按列求均值
2 example.mean(1):按行求均值
7.2 其他常用的描述性统计函数
Series 与 DataFrame 支持大量计算描述性统计的方法与操作。这些方法大部分都是 sum()、mean()、quantile() 、std()等聚合函数,其输出结果比原始数据集小;此外,还有输出结果与原始数据集同样大小的 cumsum() 、 累乘cumprod()、累积最大值cummax()、累积最小值cummin() 等函数。这些方法都基本上都接受 axis 参数。kurt(),skew(),var(),median(),min(),max(),count(),
8 DataFrame的合并处理
8.1 concat()函数
pd.concat(objs, axis=0, join=‘outer’ or ‘inner’, ignore_index=False, keys=None,
levels=None, names=None, verify_integrity=False, copy=True)
import pandas as pd
pd.concat([df[:3], df[3:7], df[7:]]) ### 逐行逐行进行合并
### application of "keys" parameter
example2 = pd.concat(example, keys=['x', 'y', 'z'])
example2.loc['y']
result = pd.concat([df1, df4], axis=1, sort=False)
8.2 append()函数
### some example about append()
example = pd.DataFrame(np.random.randn(8, 4), columns=['A', 'B', 'C', 'D'])
raw_1 = example.iloc[3]
example.append(raw_1, ignore_index=True)
### default "axis=0", 在DataFrame的最后一行后新增一行,并且忽略index
result = example.append(example, sort=False) ### 不排序
result = example1.append([example1, example2])
### append all the example, example1, example2
result = pd.concat([exmaple, example1], ignore_index=True, sort=False)
### ignore the index
result = pd.concat([example, s1], axis=1, ignore_index=True)
### notice that "axis=1" and ignore index would lead to
### "drop all name references(columns names)"
result = pd.concat([example,example1,example2], keys=['x', 'y', 'z'])
### which is similar to the function of "keys" in "concat"
pieces = {'x': df1, 'y': df2, 'z': df3}
result = pd.concat(pieces)
result = pd.concat(pieces, keys=['z', 'y'])
### combine the "dictionary" and "keys" in "concat"
8.3 join() 函数
import pandas as pd
import numpy as np
result = left.join(right) ### default: left inner join
result = left.join(right, how='outer')
result = left.join(right, how='inner')
result = left.join(right, on='key')
### "on='key'" means that the join key comes from the "key" column of the left table;
### it would search the key words from the right table to combine these 2 tables.
### Joining on multiple keys
result = left.join(right, on=['key1', 'key2'])
### join() has lsuffix and rsuffix arguments
left = left.set_index('k'); right = right.set_index('k')
result = left.join(right, lsuffix='_l', rsuffix='_r')
### Joining multiple DataFrames
result = left.join([right, right2])
8.4 merge()函数
类似于SQL 风格的表格合并。感觉类似于SQL的inner join
pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True,
suffixes=(’_x’, ‘_y’), copy=True, indicator=False,
validate=None)
解释:
1 how: ‘left’, ‘right’, ‘outer’, ‘inner’. Defaults to “inner”
2 validate: string, default None. If specified, checks if merge is of specified type.
“one_to_one” or “1:1”: checks if merge keys are unique in both left and right datasets.
“one_to_many” or “1:m”: checks if merge keys are unique in left dataset.
“many_to_one” or “m:1”: checks if merge keys are unique in right dataset.
“many_to_many” or “m:m”: allowed, but does not result in checks.
3 indicator: If True, a Categorical-type column called _merge will be added to the output object that takes on values.(类似于SAS “merge” 中的 “in” 含义)
left_only; right_only; both
import pandas as pd
left = pd.DataFrame({'key': ['aa', 'aa'], 'left': [1, 2]})
right = pd.DataFrame({'key': ['aa', 'aa'], 'right': [1.1, 2.2]})
print(left)
### output:
### key left
### 0 aa 1
### 1 aa 2
print(right)
### output:
### key right
### 0 aa 1.1
### 1 aa 2.2
pd.merge(left, right, on='key')
### output:
### key left right
### 0 aa 1 1.1
### 1 aa 1 2.2
### 2 aa 2 1.1
### 3 aa 2 2.2
### the example of "category' and "merge"
from pandas.api.types import CategoricalDtype
import pandas as pd
import numpy as np
X = pd.Series(np.random.choice(['foo', 'bar'], size=(10,)))
X1 = X.astype(CategoricalDtype(categories=['foo', 'bar']))
left = pd.DataFrame({'X': X1,\
'Y': np.random.choice(['one', 'two', 'three'],\
size=(10,))})
left.dtypes
### output:
### X category
### Y object
### dtype: object
### Joining on index
result = pd.merge(left, right, left_index=True, right_index=True, how='outer')
result = pd.merge(left, right, left_index=True, right_index=True, how='inner')
result = left.join(right, on='key')
### or
result = pd.merge(left, right, left_on='key', right_index=True,\
how='left', sort=False)
### the above equations would get the same results
### the application of "suffixes"
result = pd.merge(left, right, on='k', suffixes=['_l', '_r'])
8.5 combine_first()函数
如果我们要合并两个相似的数据集,两个数据集里的其中一个的数据比另一个多。即其中一个是“高质量”指标,另一个是“低质量”指标。一般来说,低质量序列可能包含更多的历史数据,或覆盖更广的数据。因此,要合并这两个 DataFrame 对象,其中一个 DataFrame 中的缺失值将按指定条件用另一个DataFrame 里类似标签中的数据进行填充。要实现这一操作便可以使用combine_first()函数。
import pandas as pd
example1.combine_first(example2)
8.6 MultiIndexes
leftindex = pd.MultiIndex.from_product([list('abc'), list('xy'), [1, 2]],\
names=['abc', 'xy', 'num'])
left = pd.DataFrame({'v1': range(12)}, index=leftindex)
rightindex = pd.MultiIndex.from_product([list('abc'), list('xy')],\
names=['abc', 'xy'])
right = pd.DataFrame({'v2': [100 * i for i in range(1, 7)]}, index=rightindex)
left.join(right, on=['abc', 'xy'], how='inner')
8.7 ???merge_ordered()
A merge_ordered()function allows combining time series and other ordered data. In particular it has an optional fill_method keyword to fill/interpolate missing data.
result=DataFrame.merge_ordered(left, right, on=None, left_on=None, right_on=None, left_by=None, right_by=None,fill_method=None, suffixes=’_x’, ‘_y’, how: str = ‘outer’)
left = pd.DataFrame({'k': ['K0', 'K1', 'K1', 'K2'],\
'lv': [1, 2, 3, 4],\
's': ['a', 'b', 'c', 'd']})
In [131]: right = pd.DataFrame({'k': ['K1', 'K2', 'K4'],\
'rv': [1, 2, 3]})
pd.merge_ordered(left, right, fill_method='ffill', left_by='s')
### ?the final result would order by the key column "s" and combine by the key column "k"
9 Groupby()分组函数
分组函数一般和size计数和sum求和等常用计算函数结合起来一起使用
import numpy as np
import pandas as pd
example.groupby('A').sum() ### 先分组,再用 sum()函数计算每组的汇总数据
example.groupby(['A', 'B']).sum() ### 多列分组后,生成多层索引,也可以应用 sum 函数
example.groupby(['X'], sort=False).sum() ### 同时也可以用sort参数完成排序操作
example.groupby('X').get_group('A')
example.groupby('X', axis=1).groups ### 利用groups生成dictionary
10 DataFrame的堆砌Stack
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz','foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two','one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
example = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
example2 = example[:4]
print(example2)
### output:
### A B
### first second
### bar one 0.029399 -0.542108
### two 0.282696 -0.087302
### baz one -1.575170 1.771208
### two 0.816482 1.100230
### stack()方法把DataFrame列压缩至一层
stacked = example2.stack()
print(stacked)
### output:
### first second
### B -0.542108
### two A 0.282696
### B -0.087302
### baz one A -1.575170
### B 1.771208
### two A 0.816482
### B 1.100230
### dtype: float64
### 压缩后的DataFrame或Series具有多层索引
### stack()的逆操作是unstack(),默认为拆叠最后一层
print(stacked.unstack())
print(stacked.unstack(1))
print(stacked.unstack(0))
### output:
### A B
### first second
### bar one 0.029399 -0.542108
### two 0.282696 -0.087302
### baz one -1.575170 1.771208
### two 0.816482 1.100230
### second one two
### first
### bar A 0.029399 0.282696
### B -0.542108 -0.087302
### baz A -1.575170 0.816482
### B 1.771208 1.100230
### first bar baz
### second
### one A 0.029399 -1.575170
### B -0.542108 1.771208
### two A 0.282696 0.816482
### B -0.087302 1.100230
11 DataFrame的数据透视表
example = pd.DataFrame({'A': ['one', 'one', 'two', 'three'] * 3,'B': ['A', 'B', 'C'] * 4,'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,'D': np.random.randn(12), 'E': np.random.randn(12)})
### 用pivot_table()生成数据透视表
print(pd.pivot_table(example, values='D', index=['A', 'B'], columns=['C']))
### output:
### C bar foo
### A B
### one A -0.773723 1.418757
### B -0.029716 -1.879024
### C -1.146178 0.314665
### three A 1.006160 NaN
### B NaN -1.035018
### C 0.648740 NaN
### two A NaN 0.100900
### B -1.170653 NaN
### C NaN 0.536826
12 DataFrame的分类处理
12.1 category处理
对于处理标签类型变量时使用,如逻辑回归,Classification Methods
### 生成DataFrame
example = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6],"raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})
print(example)
### 将grade的原始数据转换为类别型数据
example["grade"] = example["raw_grade"].astype("category")
print(example["grade"])
### ouytput:
### 0 a
### 1 b
### 2 b
### 3 a
### 4 a
### 5 e
### Name: grade, dtype: category
### Categories (3, object): [a, b, e]
### 用有含义的名字重命名不同类型,调用 Series.cat.categories。
example["grade"] = example["raw_grade"].cat.categories = ["very good", "good", "very bad"]
### 重新排序各类别,并添加缺失类,Series.cat 的方法默认返回新 Series。
example["grade"] = example["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
print(example["grade"])
### output:
### 0 very good
### 1 good
### 2 good
### 3 very good
### 4 very good
### 5 very bad
### Name: grade, dtype: category
### Categories (5, object): [very bad, bad, medium, good, very good]
### 注意,这里是按生成类别时的顺序排序,不是按词汇排序
df.sort_values(by="grade")
### output:
### id raw_grade grade
### 5 6 e very bad
### 1 2 b good
### 2 3 b good
### 0 1 a very good
### 3 4 a very good
### 4 5 a very good
### 按类列分组(groupby)时,即便某类别("medium", "bad")为空,也会显示。
df.groupby("grade").size()
### output:
### grade
### very bad 1
### bad 0
### medium 0
### good 2
### very good 3
### dtype: int64
### 根据观察,先需要调用cat.categories()使类型标签一一对应(a-"very good", b-"good", e-"very bad"), 之后继续调用cat.set_categories()可以使标签类型变量更加完整,没有的变量被添加缺失值。
### 生成DataFrame时,直接将变量定义为category类型
example=pd.DataFrame({'A': list('abca'), 'B': list('bccd')}, dtype="category")
example.dtypes
### output:
### A category
### B category
### dtype: object
from pandas.api.types import CategoricalDtype
s = pd.Series(["a", "b", "c", "a"])
cat_type = CategoricalDtype(categories=["b", "c", "d"],ordered=True)
s_cat = s.astype(cat_type)
print(s_cat)
### output:
### 0 NaN
### 1 b
### 2 c
### 3 NaN
### dtype: category
### Categories (3, object): [b < c < d]
12.2 cut()
cut的功能主要是给numeric类型变量划分一系列区间,为之后的category处理做准备。
import numpy as np
import pandas as pd
np.random.seed(666)
### 指定多个区间
bins = [0, 20, 40, 60, 80, 100]
series = np.random.randint(0, 100, size=50)
cut = pd.cut(series, bins)
print(pd.value_counts(cut)) ### 统计每个区间人数
之后,还可以继续了解更多关于category的处理以及pandas.qcut()的处理。
13 DataFrame的比较操作
1 eq equal to 等于
2 ne not equal to 不等于
3 lt less than 小于
4 gt greater than 大于
5 le less than or equal to 小于等于
6 ge greater than or equal to 大于等于
example.gt(example2) ### 比较example和example2是否相等
### output:
### one two three
### a False False False
### b False False False
### c False False False
### d False False False
13.1 布尔简化
empty、any()、all()、bool() 可以把数据汇总简化至单个布尔值。
### all()代表前面式子均要成立才返回“true”
(example > 0).all()
### output:
### one False
### two True
### three False
### dtype: bool
### any()代表前面式子只要满足一个就返回“true”
(example > 0).any()
### output:
### one True
### two True
### three True
### dtype: bool
### 进一步把上面的结果简化为单个布尔值
(example > 0).any().any()
### output:
### True
### 通过 empty 属性,可以验证Pandas对象是否为空。
example.empty
### output: False
pd.DataFrame(columns=list('aaa')).empty
### output: True
### 用bool()方法验证单元素pandas对象的布尔值。
pd.Series([True]).bool()
### output: True
13.2 有关列表间的nan值比较
### 使用下面等式,两个NaN值的比较结果为不等
example + example == example * 2
### output:
### one two three
### a True True False
### b True True True
### c True True True
### d False True True
### 使用equals()方法,用这个方法验证NaN值的结果为相等。
(example + example).equals(example * 2)
### output:
### True
13.3 其他相关问题
Series 与 DataFrame 索引的顺序必须一致,验证结果才能为 True;
Pandas 还能对比两个等长 array 对象里的数据元素,但注意需要等长;
14 DataFrame的函数应用
14.1 pipe()
表级函数应用:
(df.pipe(h)
… .pipe(g, arg1=1)
… .pipe(f, arg2=2, arg3=3))
解释:上述表达式为链式方法。在链式方法中调用自定义函数或第三方支持库函数时,用 pipe 更容易,与用 Pandas 自身方法一样。上例中,f、g 与 h 这几个函数都把 DataFrame 当作首位参数。要是想把数据作为第二个参数,.pipe 把 DataFrame 作为元组里指定的参数,即pipe(function,‘data’)。
(bb.query('h > 0')
.assign(ln_h=lambda df: np.log(df.h))
.pipe((sm.ols, 'data'), 'hr ~ ln_h + year + g + C(lg)')
.fit()
.summary()
)
14.2 apply()
行列级函数应用:
使用apply(),可以实现将括号中的函数对DataFrame的每一列或每一行进行类似list的处理,apply(function)对列进行处理;apply(function,axis=1)则是对行进行处理。
import numpy as np
import pandas as pd
example.apply(np.cumsum)
### output:
### A B C D F
### 2013-01-01 0.000000 0.000000 -1.509059 5 NaN
### 2013-01-02 1.212112 -0.173215 -1.389850 10 1.0
### 2013-01-03 0.350263 -2.277784 -1.884779 15 3.0
### 2013-01-04 1.071818 -2.984555 -2.924354 20 6.0
### 2013-01-05 0.646846 -2.417535 -2.648122 25 10.0
### 2013-01-06 -0.026844 -2.303886 -4.126549 30 15.0
example.apply(lambda x: x.max() - x.min())
### output:
### A 2.073961
### B 2.671590
### C 1.785291
### D 0.000000
### F 4.000000
### dtype: float64
### apply() 方法还支持通过函数名字符串调用函数。
example.apply('mean')
14.3 agg()
应用单个函数或者聚合多个函数使用:
### 应用单个函数,类似于apply()函数
example.agg(np.sum)
### 聚合多个函数
print(example.agg(['sum', 'mean']))
### output:
### A B C
### sum 3.033606 -1.803879 1.575510
### mean 0.505601 -0.300647 0.262585
### or
example.A.agg(['sum', lambda x: x.mean()])
### 用字典实现聚合
example.agg({'A': 'mean', 'B': 'sum'})
### output:
### A 0.505601
### B -1.803879
### dtype: float64
### or
example.agg({'A': ['mean', 'min'], 'B': 'sum'})
### output:
### A B
### mean 0.505601 NaN
### min -0.749892 NaN
### sum NaN -1.803879
14.4 transform()
该方法的返回结果与原始数据的索引相同,大小相同。与 .agg API 类似。
import pandas as pd
import numpy as np
### transform() 调用多个函数时,生成多层索引 DataFrame。第一层是原始数据集的列名;第二层是 transform() 调用的函数名。
example.transform([np.abs, lambda x: x + 1])
### output:
### A B C
### absolute <lambda> absolute <lambda> absolute <lambda>
### 2000-01-01 0.428759 0.571241 0.864890 0.135110 0.675341 0.324659
### 2000-01-02 0.168731 0.831269 1.338144 2.338144 1.279321 -0.279321
### 2000-01-03 1.621034 -0.621034 0.438107 1.438107 0.903794 1.903794
### 2000-01-04 NaN NaN NaN NaN NaN NaN
### 2000-01-05 NaN NaN NaN NaN NaN NaN
### 2000-01-06 NaN NaN NaN NaN NaN NaN
### 2000-01-07 NaN NaN NaN NaN NaN NaN
### 2000-01-08 0.254374 1.254374 1.240447 -0.240447 0.201052 0.798948
### 2000-01-09 0.157795 0.842205 0.791197 1.791197 1.144209 -0.144209
### 2000-01-10 0.030876 0.969124 0.371900 1.371900 0.061932 1.061932
### transform() 的参数是列表字典时,生成的是以 transform() 调用的函数为名的多层索引 DataFrame。
example.transform({'A': np.abs, 'B': [lambda x: x + 1, 'sqrt']})
### A B
### absolute <lambda> sqrt
### 2000-01-01 0.428759 0.135110 NaN
### 2000-01-02 0.168731 2.338144 1.156782
### 2000-01-03 1.621034 1.438107 0.661897
### 2000-01-04 NaN NaN NaN
### 2000-01-05 NaN NaN NaN
### 2000-01-06 NaN NaN NaN
### 2000-01-07 NaN NaN NaN
### 2000-01-08 0.254374 -0.240447 NaN
### 2000-01-09 0.157795 1.791197 0.889493
### 2000-01-10 0.030876 1.371900 0.609836
14.5 applymap()
元素级函数应用:
并非所有函数都能矢量化,即接受 NumPy 数组,返回另一个数组或值,DataFrame 的 applymap() 及 Series 的 map() ,支持任何接收单个值并返回单个值的 Python 函数。
def f(x):
return len(str(x))
example['one'].map(f)
example.applymap(f)
### Series.map() 还有个功能,可以“连接”或“映射”第二个 Series 定义的值。
### 这个功能与 merging/joining 功能联系非常紧密。
example= pd.Series(['six', 'seven', 'six', 'seven', 'six'],\
index=['a', 'b', 'c', 'd', 'e'])
example1 = pd.Series({'six': 6., 'seven': 7.})
example.map(example1)
### output:
### a 6.0
### b 7.0
### c 6.0
### d 7.0
### e 6.0
### dtype: float64
15 字符串处理
1 s.str.lower(), s.str.upper(), 大小写转换
2 idx.str.strip(),idx.str.lstrip(),idx.str.rstrip(),去空格
3 清理开头和结尾的白空格,将所有的名称都换为小写,并且将其余的空格都替换为下划线:
df.columns.str.strip().str.lower().str.replace(’ ‘, ‘’)
4 拆分字符串: s2.str.split(’’, expand=True); 限制切分的次数:s2.str.split(’_’, expand=True, n=1)
5 rsplit与split相似,不同的是,这个切分的方向是反的。即,从字串的尾端向首段切分。
6 拼接序列或者数据表:example.str.cat(example1);s.str.cat(v, join=‘left’, na_rep=’-’)
7 将一个序列与多个对象拼接为一个新的序列:s.str.cat([u, u.to_numpy()], join=‘left’)
16 常用计算工具
1 cov(): example[‘a’].cov(example1[‘a’]),用来计算两列之间的协方差,直接对DataFrame使用cov()的话会得到一个协方差矩阵。
2 corr(): example[‘a’].corr(example[‘b’]),用来计算两列之间的相关系数,直接对DataFrame使用corr()的话会得到一个相关系数矩阵。
3 corrwith(): 对不同的两个DataFrame的有相同名字的列或者index求correlation,example1.corrwith(example2),example1.corrwith(exampl2, axis=1)
4 rolling() and expanding():
window: size of moving window
min_periods: threshold of non-null data points to require (otherwise result is NA)
center: boolean, whether to set the labels at the center (default is False)
import pandas as pd
import numpy as np
example1 = example['b'].rolling(window=60)
example1.mean()
example = pd.DataFrame(np.random.randn(1000, 4),\
index=pd.date_range('1/1/2000', periods=1000),\
columns=['A', 'B', 'C', 'D'])
example1 = example.cumsum()df.rolling(window=60).sum().plot(subplots=True)
example1.rolling(window=60).sum().plot(subplots=True)
18 Plot()
example.plot(style=‘k–’)
example.mean().plot(style=‘k’)
利用pandas module完成数据导入输出
1 CSV文件导入及输出
import numpy as np
import pandas as pd
### 写入文件
example.to_csv('C:\\Users\\Leoxs\\Desktop\\example.csv')
### 导入文件
example=pd.read_csv('C:\\Users\\Leoxs\\Desktop\\example.csv')
2 Excel文件的导入及输出
import numpy as np
import pandas as pd
### 写入文件
example.to_excel('example.xlsx', sheet_name='Sheet1')
### 导入文件
example=pd.read_excel('example.xlsx', 'Sheet1', index_col=None, na_values=['NA'])