Pandas基本介绍
像Excel一样使用python进行数据分析
Numpy 和 Pandas 有什么不同
如果用 python 的列表和字典来作比较, 那么可以说 Numpy 是列表形式的,没有数值标签,而 Pandas 就是字典形式。
Pandas是基于Numpy构建的,让Numpy为中心的应用变得更加简单。
要使用pandas,首先需要了解他主要两个数据结构:Series和DataFrame。
series(系列,连续) 英 /'sɪəriːz; -rɪz/ 美 /'sɪriz/
Series是一种类似于一维数组的对象,它由一组数组(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成
仅由一组数据即可产生最简单的Series:
Series 和 DataFrame
这两个核心数据结构,他们分别代表着一维的序列和二维的表结构。
基于这两种数据结构,Pandas 可以对数据进行导入、清洗、处理、
统计和输出。
Series
Series 是个定长的字典序列。说是定长是因为在存储的时候,相当于两个 ndarray,这也
是和字典结构最大的不同。因为在字典的结构里,元素的个数是不固定的。
Series有两个基本属性:index 和 values。
在 Series 结构中,index 默认是 0,1,2,……递
增的整数序列,当然我们也可以自己来指定索引,比如 index=[‘a’, ‘b’, ‘c’,
‘d’]。
import pandas as pd obj=pd.Series([1,2,3]) obj2=pd.Series([1,2,3],index=('a','b','c')) print(obj,type(obj)) print(obj2,type(obj2)) # 字典的方式来创建 Series,比如: a={'a':1,'b':2,'c':3} print(pd.Series(a)) 0 1 1 2 2 3 dtype: int64 <class 'pandas.core.series.Series'> a 1 b 2 c 3 dtype: int64 <class 'pandas.core.series.Series'> a 1 b 2 c 3 dtype: int64
DataFrame 类型数据结构类似数据库表。
def __init__(self, data=None, index=None, columns=None, dtype=None, copy=False):
# 行index 列columns
import pandas as pd obj = pd.Series([4,7,-5,3]) # 对应索引和值 print(obj) 0 4 1 7 2 -5 3 3 dtype: int64 # Series的字符串表现形式为:索引在左边,值在右边。 # 由于我们没有为数据指定索引。于是会自动创建一个0到N-1(N为长度)的整数型索引。 # 可以通过Series的values和index属性获取其数组表示形式和索引对象 print(obj.values) print(obj.index) [ 4 7 -5 3] RangeIndex(start=0, stop=4, step=1) # 可以自己创建索引 obj2 = pd.Series([4,7,-5,3],index=['d','b','a','c']) print(obj2) d 4 b 7 a -5 c 3 dtype: int64 # 根据索引取值 print(obj2['a']) print(obj2[['c','a','d']]) -5 c 3 a -5 d 4 dtype: int64 import pandas as pd import numpy as np # nan=none s = pd.Series([1,3,6,np.nan,44,1]) print(s) 0 1.0 1 3.0 2 6.0 3 NaN 4 44.0 5 1.0 dtype: float64 # DataFrame是一个表格型的数据结构,它包含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔值等) # DataFrame既有行索引也有列索引, 它可以被看做由Series组成的大字典。 dates = pd.date_range('20190207',periods=6) # periods=6 生成6个数据 # np的random函数 # numpy中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中。 # numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样本值。 # numpy.random.rand(d0, d1, …, dn)的随机样本位于[0, 1)中。 df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=['a','b','c','d']) # 行index 列columns print(df)
a b c d 2019-02-07 -0.292233 0.422153 2.262461 0.179207 2019-02-08 1.982641 1.299313 -1.000942 -0.041675 2019-02-09 1.162939 -0.296554 1.437283 -0.104282 2019-02-10 -2.609355 -0.188624 1.161949 -0.510447 2019-02-11 -0.277941 -0.542832 -1.356549 1.004631 2019-02-12 -0.258218 0.635150 1.513197 -1.672800
print(df['b']) 2019-02-07 0.422153 2019-02-08 1.299313 2019-02-09 -0.296554 2019-02-10 -0.188624 2019-02-11 -0.542832 2019-02-12 0.635150 Freq: D, Name: b, dtype: float64 #我们在创建一组没有给定行标签和列标签的数据 df1: df1 = pd.DataFrame(np.arange(12).reshape((3,4))) # 默认index从0开始 print(df1) 0 1 2 3 0 0 1 2 3 1 4 5 6 7 2 8 9 10 11 # 字典的方式 df2 = pd.DataFrame({'A' : 1., 'B' : pd.Timestamp('20130102'), 'C' : pd.Series(1,index=list(range(4)),dtype='float32'), 'D' : np.array([3] * 4,dtype='int32'), 'E' : pd.Categorical(["test","train","test","train"]), 'F' : 'foo'}) print(df2) A B C D E F 0 1.0 2013-01-02 1.0 3 test foo 1 1.0 2013-01-02 1.0 3 train foo 2 1.0 2013-01-02 1.0 3 test foo 3 1.0 2013-01-02 1.0 3 train foo # 这种方法能对每一列的数据进行特殊对待. 如果想要查看数据中的类型, 我们可以用 dtype 这个属性: print(df2.dtypes) A float64 B datetime64[ns] C float32 D int32 E category F object dtype: object print(df2.index) Int64Index([0, 1, 2, 3], dtype='int64') # 同样, 每种数据的名称也能看到: print(df2.columns) Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object') # 如果只想看所有df2的值: print(df2.values) [[1.0 Timestamp('2013-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2013-01-02 00:00:00') 1.0 3 'train' 'foo'] [1.0 Timestamp('2013-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2013-01-02 00:00:00') 1.0 3 'train' 'foo']] # 想知道数据的总结, 可以用 describe(): print(df2.describe()) A C D count 4.0 4.0 4.0 mean 1.0 1.0 3.0 std 0.0 0.0 0.0 min 1.0 1.0 3.0 25% 1.0 1.0 3.0 50% 1.0 1.0 3.0 75% 1.0 1.0 3.0 max 1.0 1.0 3.0 # 如果想翻转数据, transpose: print(df2.T) 0 1 2 A 1 1 1 B 2013-01-02 00:00:00 2013-01-02 00:00:00 2013-01-02 00:00:00 C 1 1 1 D 3 3 3 E test train test F foo foo foo 3 A 1 B 2013-01-02 00:00:00 C 1 D 3 E train F foo # 如果想对数据的 index 进行排序并输出: # ascending=False 倒的序列进行排序 print(df2.sort_index(axis=1, ascending=False)) F E D C B A 0 foo test 3 1.0 2013-01-02 1.0 1 foo train 3 1.0 2013-01-02 1.0 2 foo test 3 1.0 2013-01-02 1.0 3 foo train 3 1.0 2013-01-02 1.0 # 如果是对数据 值 排序输出: print(df2.sort_values(by='E')) A B C D E F 0 1.0 2013-01-02 1.0 3 test foo 2 1.0 2013-01-02 1.0 3 test foo 1 1.0 2013-01-02 1.0 3 train foo 3 1.0 2013-01-02 1.0 3 train foo
数据的导入和导出
数据清洗
# 1. 删除 DataFrame 中的不必要的列或行
# 清洗数据 import pandas as pd data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98,90,89,92]} df2 = pd.DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei']) print(df2) # 1. 删除 DataFrame 中的不必要的列或行 df2=df2.drop(columns='Chinese') print(df2) df2=df2.drop(index='ZhangFei') print(df2) Chinese English Math ZhangFei 66 65 30 GuanYu 95 85 98 ZhaoYun 93 92 90 HuangZhong 90 88 89 DianWei 80 90 92 English Math ZhangFei 65 30 GuanYu 85 98 ZhaoYun 92 90 HuangZhong 88 89 DianWei 90 92 English Math GuanYu 85 98 ZhaoYun 92 90 HuangZhong 88 89 DianWei 90 92
2. 重命名列名 columns,让列表名更容易识别
df2.rename(columns={'English': '英语'}, inplace = True) df2.rename(index={'ZhangFei': '张飞'}, inplace = True) print(df2) Chinese 英语 Math 张飞 66 65 30 GuanYu 95 85 98 ZhaoYun 93 92 90 HuangZhong 90 88 89 DianWei 80 90 92
3. 去重复的值
数据采集可能存在重复的行,这时只要使用 drop_duplicates() 就会自动把重复的行去
掉。
date = {'a':[1,1,3,1],'b':[1,1,2,2]} df2 = pd.DataFrame(date,index={'zhang','lili','zhao','liu'}) print(df2) a b liu 1 1 lili 1 1 zhang 3 2 zhao 1 2 DataFrame的duplicated方法返回一个布尔型Series,表示各行是否重复行。 print(df2.duplicated()) liu False lili True zhang False zhao False dtype: bool 而 drop_duplicates方法,它用于返回一个移除了重复行的DataFrame 同一行,相同才删除 #print(df2.drop_duplicates())
例如,希望对名字为‘a’的列进行去重, print(df2.drop_duplicates('a'))
4. 格式问题
更改数据格式
因为很多时候数据格式不规范,我们可以使用 astype 函数来规 范数据格式,比如我们把 Chinese 字段的值改成 str 类型,或者 int64 可以这么写: date = {'a':[1,1,3,1],'b':[1,1,2,2]} df2 = pd.DataFrame(date,index={'zhang','lili','zhao','liu'},dtype=float) print(df2) print(df2.dtypes) df2['a']=df2['a'].astype('int32') print(df2.dtypes)
数据间的空格
有时候我们先把格式转成了 str 类型,是为了方便对数据进行操作,这时想要删除数据间
的空格,我们就可以使用 strip 函数:
strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
不能删除中间的字符
# 删除左右两边空格
df2['Chinese']=df2['Chinese'].map(str.strip)
# 删除左边空格
df2['Chinese']=df2['Chinese'].map(str.lstrip)
# 删除右边空格
df2['Chinese']=df2['Chinese'].map(str.rstrip)
大小写转换
from pandas import Series, DataFrame data = {'Chinese': [66]} df1= DataFrame(data) df2 = DataFrame(data, index=['ZhangFei']) df2.columns = df2.columns.str.upper() print(df2) # 全部小写 df2.columns = df2.columns.str.lower() print(df2) # 首字母大写 df2.columns = df2.columns.str.title() print(df2)
# 查找空值
数据量大的情况下,有些字段存在空值 NaN 的可能,这时就需要使用 Pandas 中的 isnull
函数进行查找。比如,我们输入一个数据表如下:
data = {'Chinese': [66,None, 93, 90,80],'English': [65, 85,None, 88, 90],'Math': [30, 98,90,89,92]} df2 = pd.DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei']) print(df2.isnull()) print(df2.isnull().any())
使用 apply 函数对数据进行清洗
apply函数是`pandas`里面所有函数中自由度最高的函数。该函数如下: DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds) 该函数最有用的是第一个参数,这个参数是函数,相当于C/C++的函数指针。 这个函数需要自己实现,函数的传入参数根据axis来定,比如axis = 1,就会把一行数据作为Series的数据 结构传入给自己实现的函数中,我们在函数中实现对Series不同属性之间的计算,返回一个结果,则apply函数 会自动遍历每一行DataFrame的数据,最后将所有结果组合成一个Series数据结构并返回。 9
比如我们想对 Chinese列的数值都进行大写转化可以用:
import pandas as pd data = {'Chinese': ['che']} df1= pd.DataFrame(data) df2 = pd.DataFrame(data, index=['ZhangFei']) df2['Chinese']=df2['Chinese'].apply(str.upper) print(df2)
使用自定义函数
import pandas as pd data = {'Chinese': [20],'Math':[46]} df2 = pd.DataFrame(data, index=['ZhangFei','zhao'],dtype=int) print(df2) # def fun(x): return 2*x # 对列值进行乘2处理 df2['Chinese']=df2['Chinese'].apply(fun) print(df2) # 新增一列: def fu(df2,n): df2['new']=(df2['Chinese']+df2['Math'])*n return df2 df2 = df2.apply(fu,axis=1,args=(2,)) print(df2)
数据统计
Pandas 和 NumPy 一样,都有常用的统计函数,如果遇到空值 NaN,会自动排除。
Pandas 选择数据
简单的筛选
根据标签 loc
根据序列 iloc
根据混合的这两种 ix
通过判断的筛选
dates = pd.date_range('20130101', periods=6) df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D']) print(df) A B C D 2013-01-01 0 1 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 10 11 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23 # 简单的筛选 # 如果我们想选取DataFrame中的数据,下面描述了两种途径, 他们都能达到同一个目的: print(df['A']) print('-------------------') print(df.A) 2013-01-01 0 2013-01-02 4 2013-01-03 8 2013-01-04 12 2013-01-05 16 2013-01-06 20 Freq: D, Name: A, dtype: int32 ------------------- 2013-01-01 0 2013-01-02 4 2013-01-03 8 2013-01-04 12 2013-01-05 16 2013-01-06 20 Freq: D, Name: A, dtype: int32 # 让选择跨越多行或多列: # 选择0:3行的数据 print(df[0:3]) print('-----------------------------') print(df['20130102':'20130104']) A B C D 2013-01-01 0 1 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 10 11 ----------------------------- A B C D 2013-01-02 4 5 6 7 2013-01-03 8 9 10 11 2013-01-04 12 13 14 15 # 根据标签 loc # 同样我们可以使用标签来选择数据 loc, 本例子主要通过标签名字选择某一行数据, # 或者通过选择某行或者所有行(:代表所有行)然后选其中某一列或几列数据。 print(df.loc['20130102']) A 4 B 5 C 6 D 7 Name: 2013-01-02 00:00:00, dtype: int32 print(df.loc[:,['A','B']]) A B 2013-01-01 0 1 2013-01-02 4 5 2013-01-03 8 9 2013-01-04 12 13 2013-01-05 16 17 2013-01-06 20 21 print(df.loc['20130102',['A','B']]) A 4 B 5 Name: 2013-01-02 00:00:00, dtype: int32 # 根据 序列 iloc # 另外我们可以采用位置进行选择 iloc, 在这里我们可以通过位置选择在不同情况下所需要的数据例如选某一个, # 连续选或者跨行选等操作。 print(df.iloc[3,1]) 13 print(df.iloc[3:5,1:3]) # 3\4两列,1,2两行 B C 2013-01-04 13 14 2013-01-05 17 18 print(df.iloc[[1,3,5],1:3]) # 行和列 B C 2013-01-02 5 6 2013-01-04 13 14 2013-01-06 21 22 # 根据混合的这两种 ix # 当然我们可以采用混合选择 ix, 其中选择’A’和’C’的两列,并选择前三行的数据。 print(df.ix[:3,['A','C']]) A C 2013-01-01 0 2 2013-01-02 4 6 2013-01-03 8 10 # 通过判断的筛选 print(df[df.A>8]) A B C D 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23
Pandas 设置值
创建数据
根据位置设置 loc 和 iloc
根据条件设置
按行或列设置
添加数据
1.loc意义:通过行标签索引行数据
例: loc[n]表示索引的是第n行(index 是整数)
loc[‘d’]表示索引的是第’d’行(index 是字符)
2. .iloc :通过行号获取行数据,不能是字符
3. ix——结合前两种的混合索引
三者区别:
ix / loc 可以通过行号和行标签进行索引,比如 df.loc['a'] , df.loc[1], df.ix['a'] , df.ix[1]
而iloc只能通过行号索引 , df.iloc[0] 是对的, 而df.iloc['a'] 是错误的
dates = pd.date_range('20130101', periods=6) df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D']) print(df) A B C D 2013-01-01 0 1 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 10 11 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23 # 根据位置设置 loc 和 iloc df.iloc[2,2] = 1111 print(df) print('---------------------------------') df.loc['20130101','B'] = 2222 print(df) A B C D 2013-01-01 0 1 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 1111 11 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23 --------------------------------- A B C D 2013-01-01 0 2222 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 1111 11 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23 # 根据条件设置 # 如果现在的判断条件是这样, 我们想要更改B中的数, 而更改的位置是取决于 A 的. # 对于A大于4的位置. 更改B在相应位置上的数为0. df.B[df.A>4] = 0 print(df) A B C D 2013-01-01 0 2222 2 3 2013-01-02 4 5 6 7 2013-01-03 8 0 1111 11 2013-01-04 12 0 14 15 2013-01-05 16 0 18 19 2013-01-06 20 0 22 23 # 按行或列设置 # 如果对整列做批处理, 加上一列 ‘F’, 并将 F 列全改为 NaN, 如下: df['F'] = np.nan print(df) A B C D F 2013-01-01 0 2222 2 3 NaN 2013-01-02 4 5 6 7 NaN 2013-01-03 8 0 1111 11 NaN 2013-01-04 12 0 14 15 NaN 2013-01-05 16 0 18 19 NaN 2013-01-06 20 0 22 23 NaN # 添加数据 # 用上面的方法也可以加上 Series 序列(但是长度必须对齐)。 df['E'] = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130101',periods=6)) print(df) A B C D F E 2013-01-01 0 2222 2 3 NaN 1 2013-01-02 4 5 6 7 NaN 2 2013-01-03 8 0 1111 11 NaN 3 2013-01-04 12 0 14 15 NaN 4 2013-01-05 16 0 18 19 NaN 5 2013-01-06 20 0 22 23 NaN 6
Pandas 处理丢失数据
创建含 NaN 的矩阵
pd.dropna()
pd.fillna()
pd.isnull()
Pandas 处理丢失数据 #有时候我们导入或处理数据, 会产生一些空的或者是 NaN 数据,如何删除或者是填补这些 NaN 数据就是我们今天所要提到的内容. #建立了一个6X4的矩阵数据并且把两个位置置为空. dates = pd.date_range('20130101', periods=6) df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D']) print(df) print('---------------------------') df.iloc[0,1] = np.nan df.iloc[1,2] = np.nan print(df) A B C D 2013-01-01 0 1 2 3 2013-01-02 4 5 6 7 2013-01-03 8 9 10 11 2013-01-04 12 13 14 15 2013-01-05 16 17 18 19 2013-01-06 20 21 22 23 --------------------------- A B C D 2013-01-01 0 NaN 2.0 3 2013-01-02 4 5.0 NaN 7 2013-01-03 8 9.0 10.0 11 2013-01-04 12 13.0 14.0 15 2013-01-05 16 17.0 18.0 19 2013-01-06 20 21.0 22.0 23 # pd.dropna() # 如果想直接去掉有 NaN 的行或列, 可以使用 dropna a = df.dropna( axis=0, # 0: 对行进行操作; 1: 对列进行操作 how='any' # 'any': 只要存在 NaN 就 drop 掉; 'all': 必须全部是 NaN 才 drop ) print(a) A B C D 2013-01-03 8 9.0 10.0 11 2013-01-04 12 13.0 14.0 15 2013-01-05 16 17.0 18.0 19 2013-01-06 20 21.0 22.0 23 # pd.fillna() # 如果是将 NaN 的值用其他值代替, 比如代替成 0: print(df.fillna(value=0)) A B C D 2013-01-01 0 0.0 2.0 3 2013-01-02 4 5.0 0.0 7 2013-01-03 8 9.0 10.0 11 2013-01-04 12 13.0 14.0 15 2013-01-05 16 17.0 18.0 19 2013-01-06 20 21.0 22.0 23 # pd.isnull() # 判断是否有缺失数据 NaN, 为 True 表示缺失数据: print(df.isnull()) A B C D 2013-01-01 False True False False 2013-01-02 False False True False 2013-01-03 False False False False 2013-01-04 False False False False 2013-01-05 False False False False 2013-01-06 False False False False # 检测在数据中是否存在 NaN, 如果存在就返回 True:'' np.any(df.isnull()) == True True
Pandas 导入导出
读取和保存的格式
pandas可以读取与存取的资料格式有很多种,像csv、excel、json、html与pickle等…, 详细请看官方说明文件 读取csv import pandas as pd #加载模块 #读取csv data = pd.read_csv('student.csv') #打印出data print(data) Student ID name age gender 0 1100 Kelly 22 Female 1 1101 Clo 21 Female 2 1102 Tilly 22 Female 3 1103 Tony 24 Male 4 1104 David 20 Male 5 1105 Catty 22 Female 6 1106 M 3 Female 7 1107 N 43 Male 8 1108 A 13 Male 9 1109 S 12 Male 10 1110 David 33 Male 11 1111 Dw 3 Female 12 1112 Q 23 Male 13 1113 W 21 Female 将资料存取成pickle data.to_pickle('student.pickle')
读取excel import pandas as pd data = pd.read_excel('病历数据.xlsx','Sheet2') print(data) 默认读取Sheet1表的数据,可以指定读取具体表
Pandas 合并 concat
要点
axis (合并方向)
ignore_index (重置 index)
join (合并方式)
join_axes (依照 axes 合并)
append (添加数据)
pandas处理多组数据的时候往往会要用到数据的合并处理,使用 concat是一种基本的合并方式.
而且concat中有很多参数可以调整,合并成你想要的数据形式.
# axis (合并方向) # axis=0是预设值,因此未设定任何参数时,函数默认axis=0。 import pandas as pd import numpy as np #定义资料集 df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d']) df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d']) df3 = pd.DataFrame(np.ones((3,4))*2, columns=['a','b','c','d']) #concat 纵向(axis=0)合并 res = pd.concat([df1, df2, df3], axis=0) #打印结果 print(res) a b c d 0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 0 1.0 1.0 1.0 1.0 1 1.0 1.0 1.0 1.0 2 1.0 1.0 1.0 1.0 0 2.0 2.0 2.0 2.0 1 2.0 2.0 2.0 2.0 2 2.0 2.0 2.0 2.0 # numpy中的zeros(),ones()函数 # zeros()返回一个全0的n维数组,一共有三个参数:shape(用来指定返回数组的大小)、dtype(数组元素的类型)、order(是否以内存中的C或Fortran连续(行或列)顺序存储多维数据)。 # 后两个参数都是可选的,一般只需设定第一个参数。 # ones()返回一个全1的n维数组,同样也有三个参数:shape(用来指定返回数组的大小)、dtype(数组元素的类型)、order(是否以内存中的C或Fortran连续(行或列)顺序存储多维数据)。 # 后两个参数都是可选的,一般只需设定第一个参数。和zeros一样 # ignore_index (重置 index) #承上一个例子,并将index_ignore设定为True 纵向(axis=0)合并 res = pd.concat([df1, df2, df3], axis=0, ignore_index=True) #打印结果 print(res) a b c d 0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 3 1.0 1.0 1.0 1.0 4 1.0 1.0 1.0 1.0 5 1.0 1.0 1.0 1.0 6 2.0 2.0 2.0 2.0 7 2.0 2.0 2.0 2.0 8 2.0 2.0 2.0 2.0 # join (合并方式) # join='outer'为预设值,因此未设定任何参数时,函数默认join='outer'。 # 此方式是依照column来做纵向合并,有相同的column上下合并在一起, # 其他独自的column个自成列,原本没有值的位置皆以NaN填充。 import pandas as pd import numpy as np #定义资料集 df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'], index=[1,2,3]) df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4]) #纵向"外"合并df1与df2 res = pd.concat([df1, df2], axis=0, join='outer') print(res) a b c d e 1 0.0 0.0 0.0 0.0 NaN 2 0.0 0.0 0.0 0.0 NaN 3 0.0 0.0 0.0 0.0 NaN 2 NaN 1.0 1.0 1.0 1.0 3 NaN 1.0 1.0 1.0 1.0 4 NaN 1.0 1.0 1.0 1.0 #承上一个例子 #纵向"内"合并df1与df2,,,inner合并相同的部分 res = pd.concat([df1, df2], axis=0, join='inner') #打印结果 print(res) print('-------------------------') #重置index并打印结果 res = pd.concat([df1, df2], axis=0, join='inner', ignore_index=True) print(res) b c d 1 0.0 0.0 0.0 2 0.0 0.0 0.0 3 0.0 0.0 0.0 2 1.0 1.0 1.0 3 1.0 1.0 1.0 4 1.0 1.0 1.0 ------------------------- b c d 0 0.0 0.0 0.0 1 0.0 0.0 0.0 2 0.0 0.0 0.0 3 1.0 1.0 1.0 4 1.0 1.0 1.0 5 1.0 1.0 1.0 # join_axes (依照 axes 合并) import numpy as np import pandas as pd df1 = pd.DataFrame(np.ones((3,4))*0,columns=['a','b','c','d'],index=[1,2,3]) df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4]) #依照`df1.index`进行横向合并 res = pd.concat([df1, df2], axis=1, join_axes=[df1.index]) #打印结果 print(res) a b c d b c d e 1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 3 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 #移除join_axes,并打印结果 res = pd.concat([df1, df2], axis=1) print(res) a b c d b c d e 1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 3 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 4 NaN NaN NaN NaN 1.0 1.0 1.0 1.0
append (添加数据)
# append只有纵向合并,没有横向合并。 import pandas as pd import numpy as np #定义资料集 df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d']) df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d']) df3 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d']) s1 = pd.Series([1,2,3,4], index=['a','b','c','d']) #将df2合并到df1的下面,以及重置index,并打印出结果 res = df1.append(df2, ignore_index=True) print(res) a b c d 0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 3 1.0 1.0 1.0 1.0 4 1.0 1.0 1.0 1.0 5 1.0 1.0 1.0 1.0 #合并多个df,将df2与df3合并至df1的下面,以及重置index,并打印出结果 res = df1.append([df2, df3], ignore_index=True) print(res) a b c d 0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 3 1.0 1.0 1.0 1.0 4 1.0 1.0 1.0 1.0 5 1.0 1.0 1.0 1.0 6 1.0 1.0 1.0 1.0 7 1.0 1.0 1.0 1.0 8 1.0 1.0 1.0 1.0 #合并series,将s1合并至df1,以及重置index,并打印出结果 res = df1.append(s1, ignore_index=True) print(res) a b c d 0 0.0 0.0 0.0 0.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 3 1.0 2.0 3.0 4.0
Pandas 合并 merge
column英 /'kɒləm/美 /'kɑləm/n. 纵队,列
要点
依据一组key合并
依据两组key合并
Indicator
依据index合并
解决overlapping的问题
pandas中的merge和concat类似,但主要是用于两组有key column的数据,统一索引的数据. 通常也被用在Database的处理当中.
数据库的处理
import pandas as pd df1 = pd.DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) df2 = pd.DataFrame({'name':['ZhangFei', 'GuanYu', 'A', 'B', 'C'], 'data2':range(5)}) # 基于 name 这列进行连接 print(pd.merge(df1,df2,on='name')) print() # inner连接 print(pd.merge(df1,df2,how='inner')) # left连接 左连接是以第一个 DataFrame 为主进行的连接 print() print(pd.merge(df1,df2,how='left')) #right 右连接是以第二个 DataFrame 为主进行的连接 print() print(pd.merge(df1,df2,how='right')) # 外连接 外连接相当于求两个 DataFrame 的并集 print() print(pd.merge(df1,df2,how='outer')) name data1 data2 0 ZhangFei 0 0 1 GuanYu 1 1 name data1 data2 0 ZhangFei 0 0 1 GuanYu 1 1 name data1 data2 0 ZhangFei 0 0.0 1 GuanYu 1 1.0 2 a 2 NaN 3 b 3 NaN 4 c 4 NaN name data1 data2 0 ZhangFei 0.0 0 1 GuanYu 1.0 1 2 A NaN 2 3 B NaN 3 4 C NaN 4 name data1 data2 0 ZhangFei 0.0 0.0 1 GuanYu 1.0 1.0 2 a 2.0 NaN 3 b 3.0 NaN 4 c 4.0 NaN 5 A NaN 2.0 6 B NaN 3.0 7 C NaN 4.0
import pandas as pd #定义资料集并打印出 left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']}) right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}) print(left) key A B 0 K0 A0 B0 1 K1 A1 B1 2 K2 A2 B2 3 K3 A3 B3 print(right) key C D 0 K0 C0 D0 1 K1 C1 D1 2 K2 C2 D2 3 K3 C3 D3
#依据key column合并,并打印出 res = pd.merge(left, right, on='key') print(res) key A B C D 0 K0 A0 B0 C0 D0 1 K1 A1 B1 C1 D1 2 K2 A2 B2 C2 D2 3 K3 A3 B3 C3 D3 # 依据两组key合并 # 合并时有4种方法how = ['left', 'right', 'outer', 'inner'],预设值how='inner'。 import pandas as pd #定义资料集并打印出 left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'], 'key2': ['K0', 'K1', 'K0', 'K1'], 'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3']}) right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'], 'key2': ['K0', 'K0', 'K0', 'K0'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}) print(left) key1 key2 A B 0 K0 K0 A0 B0 1 K0 K1 A1 B1 2 K1 K0 A2 B2 3 K2 K1 A3 B3 print(right) key1 key2 C D 0 K0 K0 C0 D0 1 K1 K0 C1 D1 2 K1 K0 C2 D2 3 K2 K0 C3 D3
#依据key1与key2 columns进行合并,并打印出四种结果['left', 'right', 'outer', 'inner'] res = pd.merge(left, right, on=['key1', 'key2'], how='inner') # 默认 inner # inner相同的部分 print(res) key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K1 K0 A2 B2 C1 D1 2 K1 K0 A2 B2 C2 D2
res = pd.merge(left, right, on=['key1', 'key2'], how='outer')
print(res) key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K0 K1 A1 B1 NaN NaN 2 K1 K0 A2 B2 C1 D1 3 K1 K0 A2 B2 C2 D2 4 K2 K1 A3 B3 NaN NaN 5 K2 K0 NaN NaN C3 D3 res = pd.merge(left, right, on=['key1', 'key2'], how='left')
print(res) key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K0 K1 A1 B1 NaN NaN 2 K1 K0 A2 B2 C1 D1 3 K1 K0 A2 B2 C2 D2 4 K2 K1 A3 B3 NaN NaN res = pd.merge(left, right, on=['key1', 'key2'], how='right')
print(res) key1 key2 A B C D 0 K0 K0 A0 B0 C0 D0 1 K1 K0 A2 B2 C1 D1 2 K1 K0 A2 B2 C2 D2 3 K2 K0 NaN NaN C3 D3 # Indicator # indicator=True会将合并的记录放在新的一列。 import pandas as pd #定义资料集并打印出 df1 = pd.DataFrame({'col1':[0,1], 'col_left':['a','b']}) df2 = pd.DataFrame({'col1':[1,2,2],'col_right':[2,2,2]})
print(df1) col1 col_left 0 0 a 1 1 b
print(df2) col1 col_right 0 1 2 1 2 2 2 2 2 # 依据col1进行合并,并启用indicator=True,最后打印出 res = pd.merge(df1, df2, on='col1', how='outer', indicator=True) print(res) col1 col_left col_right _merge 0 0 a NaN left_only 1 1 b 2.0 both 2 2 NaN 2.0 right_only 3 2 NaN 2.0 right_only # 自定indicator column的名称,并打印出 res = pd.merge(df1, df2, on='col1', how='outer', indicator='indicator_column') print(res) col1 col_left col_right indicator_column 0 0 a NaN left_only 1 1 b 2.0 both 2 2 NaN 2.0 right_only 3 2 NaN 2.0 right_only # 依据index合并 import pandas as pd #定义资料集并打印出 left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']}, index=['K0', 'K1', 'K2']) right = pd.DataFrame({'C': ['C0', 'C2', 'C3'], 'D': ['D0', 'D2', 'D3']}, index=['K0', 'K2', 'K3']) print(left) A B K0 A0 B0 K1 A1 B1 K2 A2 B2 print(right) C D K0 C0 D0 K2 C2 D2 K3 C3 D3 #依据左右资料集的index进行合并,how='outer',并打印出 res = pd.merge(left, right, left_index=True, right_index=True, how='outer') print(res) A B C D K0 A0 B0 C0 D0 K1 A1 B1 NaN NaN K2 A2 B2 C2 D2 K3 NaN NaN C3 D3 #依据左右资料集的index进行合并,how='inner',并打印出 res = pd.merge(left, right, left_index=True, right_index=True, how='inner') print(res) A B C D K0 A0 B0 C0 D0 K2 A2 B2 C2 D2 # 解决overlapping(重叠)的问题 import pandas as pd #定义资料集 boys = pd.DataFrame({'k': ['K0', 'K1', 'K2'], 'age': [1, 2, 3]}) girls = pd.DataFrame({'k': ['K0', 'K0', 'K3'], 'age': [4, 5, 6]}) #使用suffixes(后缀)解决overlapping的问题 res = pd.merge(boys, girls, on='k', suffixes=['_boy', '_girl'], how='inner') print(res) k age_boy age_girl 0 K0 1 4 1 K0 1 5
如何用 SQL 方式打开 Pandas
Pandas 的 DataFrame 数据类型可以让我们像处理数据表一样进行操作,比如数据表的增
删改查,都可以用 Pandas 工具来完成。不过也会有很多人记不住这些 Pandas 的命令,
相比之下还是用 SQL 语句更熟练,用 SQL 对数据表进行操作是最方便的,它的语句描述
形式更接近我们的自然语言。
这里给你介绍个工具:pandasql。
pandasql 中的主要函数是 sqldf,它接收两个参数:一个 SQL 查询语句,还有一组环境
变量 globals() 或 locals()。这样我们就可以在 Python 里,直接用 SQL 语句中对
DataFrame 进行操作,举个例子:
import pandas as pd from pandasql import sqldf, load_meat, load_births df1 = pd.DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) pysqldf = lambda sql: sqldf(sql, globals()) sql = "select * from df1 where name ='ZhangFei'" print (pysqldf(sql)) name data1 0 ZhangFei 0
lambda argument_list: expression 匿名函数
这里 argument_list 是参数列表,expression 是关于参数的表达式,会根据 expression
表达式计算结果进行输出返回。
练习题
# 对于下表的数据,请使用 Pandas 中的 DataFrame 进行创建,并对数据进行清洗。同时 # 新增一列“总和”计算每个人的三科成绩之和。 import pandas as pd data = {'语文':[66,95,95,90,80,80],'英语':[65,85,92,88,90,90],'数学':[None,98,96,77,90,90]} df = pd.DataFrame(data,index=['张飞','关羽','赵云','黄忠','典韦','典韦']) print(df) # 填充空值,删除重复项 # #使用score均值对NA进行填充 df['数学']=df['数学'].fillna(df['数学'].mean()) print(df) # 删除重复项 删除相同的行 df = df.drop_duplicates() print(df)
语文 英语 数学
张飞 66 65 NaN
关羽 95 85 98.0
赵云 95 92 96.0
黄忠 90 88 77.0
典韦 80 90 90.0
典韦 80 90 90.0
语文 英语 数学
张飞 66 65 90.2
关羽 95 85 98.0
赵云 95 92 96.0
黄忠 90 88 77.0
典韦 80 90 90.0
典韦 80 90 90.0
语文 英语 数学
张飞 66 65 90.2
关羽 95 85 98.0
赵云 95 92 96.0
黄忠 90 88 77.0
典韦 80 90 90.0
Pandas plot 出图
创建一个Series
Dataframe 可视化
这次我们讲如何将数据可视化. 首先import我们需要用到的模块,除了 pandas,我们也需要使用 numpy 生成一些数据,
这节里使用的 matplotlib 仅仅是用来 show 图片的, 即 plt.show()。
这是一个线性的数据,我们随机生成1000个数据,Series 默认的 index 就是从0开始的整数,但是这里我显式赋值以便让大家看的更清楚 import pandas as pd import numpy as np import matplotlib.pyplot as plt # 随机生成1000个数据 data = pd.Series(np.random.randn(1000),index=np.arange(1000)) # 为了方便观看效果, 我们累加这个数据 data.cumsum() # pandas 数据可以直接观看其可视化形式 data.plot()
就这么简单,熟悉 matplotlib 的朋友知道如果需要plot一个数据,我们可以使用 plt.plot(x=, y=),把x,y的数据作为参数存进去,但是data本来就是一个数据,所以我们可以直接plot。 生成的结果就是下图: Dataframe 可视化 我们生成一个1000*4 的DataFrame,并对他们累加 data = pd.DataFrame( np.random.randn(1000,4), index=np.arange(1000), columns=list("ABCD") ) data.cumsum() data.plot()
这个就是我们刚刚生成的4个column的数据,因为有4组数据,所以4组数据会分别plot出来。plot 可以指定很多参数,具体的用法大家可以自己查一下这里 除了plot,我经常会用到还有scatter,这个会显示散点图,首先给大家说一下在 pandas 中有多少种方法 bar或barh为条形 hist为直方图 boxplot为盒型图 area为“面积” scatter为散点图 box()箱形图 但是我们今天不会一一介绍,主要说一下 plot 和 scatter. 因为scatter只有x,y两个属性,我们我们就可以分别给x, y指定数据 # 将之下这个 data 画在上一个 ax 上面 data.plot.scatter(x='A',y='C',color='LightGreen',label='Class2',ax=ax)