Pandas 是基于 NumPy 的一个开源 Python 库,它被广泛用于快速分析数据,以及数据清洗和准备等工作。它的名字来源是由“ Panel data”(面板数据,一个计量经济学名词)两个单词拼成的。简单地说,你可以把 Pandas 看作是 Python 版的 Excel。
我喜欢 Pandas 的原因之一,是因为它很酷,它能很好地处理来自一大堆各种不同来源的数据,比如 Excel 表格、CSV 文件、SQL 数据库,甚至还能处理存储在网页上的数据。
话不多说,让我们开始吧!
Series是一种一维数组,和Numpy里的数组很相似。事实上,Series基本上就是基于Numpy的数据结构来的。但与Numpy不同的是,Series能为数组定义标签,也就是索引(index)然乎通过索引来访问数组中的数据。
import numpy as np
import pandas as pd
创建一个Series的基本语法如下:
# my_series=pd.Series(data,index)
countries = ['USA','Russia','China','France']
my_data = [100, 200, 300,150]
pd.Series(my_data,countries) #using countries as index my_data as data
与Numpy数组不同的是,series能存放不同的数据类型
np_arr = np.array(my_data)
np_arr
pd.Series(np_arr) #缺省index
pandas将字典的key自动变为index,values变为data
my_dict = {'a':50, 'b':40, 'd':60, 'c': 45}
my_dict
pd.Series(my_dict)
访问,Series离得数据方式,和python字典基本一样
my_serie = pd.Series(my_data,countries)
my_serie
my_serie['China']
对series的算数运算是基于index进行的。我们可以用加减乘除(+ - × /)这样的运算符对两个Series进行运算。Pandas将会根据index,对相应的数据进行运算。结果以float数据类型出现,防止丢失精度
my_serie2 = pd.Series([100, 300, 230, 150],['USA','Canada','China','Japan'])
my_serie2
my_serie
my_serie-my_serie2
my_serie+my_serie2
index如果是字符串,按照字母顺序排列,如果没有相同的index就返回空值NaN
Pandas 的 DataFrame(数据表)是一种 2 维数据结构,数据以表格的形式存储,分成若干行和列。通过 DataFrame,你能很方便地处理数据。常见的操作比如选取、替换行或列的数据,还能重组数据表、修改索引、多重筛选等。
构建一个 DataFrame 对象的基本语法如下
# pd.DataFrame(data,index)
表中的每一列基本上就是一个 Series ,它们都用了同一个 index。因此,我们基本上可以把 DataFrame 理解成一组采用同样索引的 Series 的集合。如下例
pd.DataFrame({'Name':pd.Series(['Bob','John','Ann','Bill']), 'Age':pd.Series([23, 24, 20,19]),
'Nationality': pd.Series(['USA','Canada','Japan','Germany'])})
#自定义index给series,所有series必须同样的index
pd.DataFrame({'Name':pd.Series(['Bob','John','Ann','Bill'],['a','b','c','d']), 'Age':pd.Series([23, 24, 20,19],['a','b','c','d']),
'Nationality': pd.Series(['USA','Canada','Japan','Germany'],['a','b','c','d'])})
#否则,比如['a','e','c','d']
pd.DataFrame({'Name':pd.Series(['Bob','John','Ann','Bill'],['a','e','c','d']), 'Age':pd.Series([23, 24, 20,19],['a','b','c','d']),
'Nationality': pd.Series(['USA','Canada','Japan','Germany'],['a','b','c','d'])})
#上面的例子可以拆分未如下表示
#Series:缺省index
# serie1=pd.Series(['Bob','John','Ann','Bill'])
# serie2=pd.Series([23, 24, 20,19])
# serie3=pd.Series(['USA','Canada','Japan','Germany'])
#字典my_dict={'Name':serie1, 'Age':serie2,
# 'Nationality': serie3}
# pd.DataFrame(my_dict)
# 基本结构 pd.DataFrame(data,index)
# pd.DataFrame(dictionary_of_list,index)
my_dataframe=pd.DataFrame({'Name':['Bob','John','Ann','Bill'], 'Age':[23, 24, 20,19],
'Nationality': ['USA','Canada','Japan','Germany']}, index = ['a','b','c','d'])
my_dataframe
#上面的例子可以拆分未如下表示
#list:缺省index
# list1=['Bob','John','Ann','Bill']
# list2= [23, 24, 20,19]
# list3=['USA','Canada','Japan','Germany']
#字典my_dict={'Name':list1, 'Age':list2,
# 'Nationality': list3}
# pd.DataFrame(my_dict,index)
与Series相似, 数据获取使用 中括号 [] 的方式
比如获取上表格中的 "name" column:
my_dataframe['Name'] #获取Name
#返回 type值
type(my_dataframe['Name'])
# 错误例子如下 my_dataframe['Name','Nationality']
my_dataframe[['Name','Nationality']]
type(my_dataframe[['Name','Nationality']])
my_dict_of_series = {'Name':pd.Series(['Bob','John','Ann','Bill'],['a','b','c','d']), 'Age':pd.Series([23, 24, 20,19],['a','b','c','d']),
'Nationality': pd.Series(['USA','Canada','Japan','Germany'],['a','b','c','d'])}
pd.DataFrame(my_dict_of_series)
# Methode 1:
# Add a new Serie in the dict
my_dict_of_series['Year'] =[2015,2016,2018,2017]
pd.DataFrame(my_dict_of_series)
# Methode 2:
# 通过编辑其他的my_dict_of_series词条 来获得新的my_dict_of_series词条
my_dict_of_series['BirthYear'] = my_dict_of_series['Year']+my_dict_of_series['Age']
my_df=pd.DataFrame(my_dict_of_series)
my_df
想要删除某一行或一列,可以用 .drop() 函数。在使用这个函数的时候,你需要先指定具体的删除方向:
请务必记住,除非用户明确指定,否则在调用 .drop() 的时候,Pandas 并不会真的永久性地删除这行/列。这主要是为了防止用户误操作丢失数据。
如果你确定要永久性删除某一行/列,你需要加上 inplace=True 参数
my_df.drop('BirthYear',axis =1)
my_df
my_df.drop('d',axis =0)
my_df
## Really Delete Something
my_df.drop('d',axis =0,inplace=True)
my_df
my_df
my_df.loc['a']
my_df.iloc[0]
my_df.iloc[[0,1]]
my_df.loc[['a','b']]
同时你可以用 .loc[] 来指定具体的行列范围,并生成一个子数据表,就像在 NumPy 里做的一样。比如,提取 'c' 行中 'Name’ 列的内容,可以如下操作:
my_df.loc['a','Age'] #先行后列
my_df.loc[['a','b'],['Age','Year']] #先行后列 用array表示行和列
用中括号 [] 的方式,除了直接指定选中某些列外,还能接收一个条件语句,然后筛选出符合条件的行/列。
my_df[my_df['Age']>20]
my_df[my_df['Age']>20]['Name']
my_df[my_df['Age']>20][['Name','Nationality']]
my_df['Age']>20
type(my_df['Age']>20)
my_df[my_df['Age']>20]
注意!!!Series的index的顺序最好与DF一致
my_df[pd.Series([True, True, False],index=['a','b','c'])]
my_df[pd.Series([True, True, False],index=['a','c','b'])]
# 查看返回类型 一个新的DataFrame
type(my_df[pd.Series([True, True, False],index=['a','b','c'])])
# 生成心得DF 且访问新的DF的某一列
my_df[pd.Series([True, True, False],index=['a','b','c'])]['Year']
# 生成心得DF 且访问新的DF的某一行
my_df[pd.Series([True, True, False],index=['a','b','c'])].iloc[1]
my_df
my_df[(my_df['Age']>20) & (my_df['Year']>2015)]
my_df[(my_df['Age']>20) | (my_df['Year']>2015)]
如果你觉得当前 DataFrame 的索引有问题,你可以用
简单地把整个表的索引都重置掉。
这个方法将把目标 DataFrame 的索引保存在一个叫 "index" 的列中,而把表格的索引变成默认的从零开始的数字,也就是 [0, ..., len(data) - 1]。比如下面这样:
my_df.reset_index()
从上面的输出可见 表格多了一列名为index的列
my_df.drop('level_0',axis=1,inplace=True)
my_df
my_df.set_index('index',inplace=True)
my_df
.reset_index() 并不会永久改变你表格的索引,除非你调用的时候明确传入了 inplace 参数,比如:.reset_index(inplace=True)
my_df.reset_index(inplace=True)
my_df
多级索引其实就是一个由元组(Tuple)组成的数组,每一个元组都是独一无二的。你可以从一个包含许多数组的列表中创建多级索引(调用 MultiIndex.from_arrays ),也可以用一个包含许多元组的数组(调用 MultiIndex.from_tuples )或者是用一对可迭代对象的集合(比如两个列表,互相两两配对)来构建(调用MultiIndex.from_product )。
下面这个例子,我们从元组中创建多级索引:
outside=['0 level','0 level', '0 level', 'A level', 'A level', 'A level']
inside=[21,22,23,21,22,23]
my_index = list(zip(outside,inside))
my_index
!!!!!zip 方法在 Python 2 和 Python 3 中的不同:在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。!!!!!
生成一个多级index
my_index=pd.MultiIndex.from_tuples(my_index)
my_index
#或者give a name
my_index1 = list(zip(outside,inside))
my_index1
多级索引需要名字
my_index1=pd.MultiIndex.from_tuples(my_index1, names=['level 1','level2'])
my_index1
生成dataframe
np.random.randn(6,2) 6 rows 2cols
my_df = pd.DataFrame(np.random.randn(6,2),index=my_index,columns=['A','B'])
my_df
my_df1 = pd.DataFrame(np.random.randn(6,2),index=my_index1,columns=['A','B'])
my_df1
还是用到 .loc[] 。比如,先获取 '0 Level' 下的数据:
my_df.loc['0 level']
my_df.loc['0 level'].loc[21,'A']
my_df.index.names=['level 1', 'level 2']
my_df
我们可以用 .xs() 方法轻松获取到多级索引中某些特定级别的数据。
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.xs.html
比如,我们需要找到所有 level 1 中,level 2 = 22 的行:
my_df.xs(22, level='level 2')
my_df.xs(('A level',23))
type(my_df.xs(('A level',23)))
type(my_df.xs(22, level='level 2'))
my_df.xs('A',axis=1)
first=['0 level','0 level', '0 level', 'A level', 'A level', 'A level']
second=['one','two','three','one','one','two']
third=[21,22,23,21,22,23]
my_multiindex1=list(zip(first,second,third))
my_multiindex1=pd.MultiIndex.from_tuples(my_multiindex1, names=['first','second','third'])
my_multiindex1
my_multiindex_df=pd.DataFrame(np.random.randn(6,3),index=my_multiindex1,columns=['A','B','C'])
my_multiindex_df
my_multiindex_df.xs(('0 level', 'three'))
my_multiindex_df.xs(('0 level', 23), level=['first','third'])
my_multiindex_df.xs('one', level='second',)
在许多情况下,如果你用 Pandas 来读取大量数据,往往会发现原始数据中会存在不完整的地方。在 DataFrame 中缺少数据的位置, Pandas 会自动填入一个空值,比如 NaN或 Null 。因此,我们可以选择用
df_with_NAN={'A':[1, np.nan,2],'B':[np.nan,np.nan,3],'C':[1,4,5]}
df_with_NAN=pd.DataFrame(df_with_NAN)
df_with_NAN
当你使用 .dropna() 方法时,就是告诉 Pandas 删除掉存在一个或多个空值的行(或者列)。删除列用的是 .dropna(axis=0) ,删除行用的是 .dropna(axis=1) 。
如果你没有指定 axis 参数,默认是删除行。
df_with_NAN.dropna()
df_with_NAN
df_with_NAN.dropna(axis=1)
df_with_NAN
类似的,如果你使用 .fillna() 方法,Pandas 将对这个 DataFrame 里所有的空值位置填上你指定的默认值。比如,将表中所有NaN 替换成 1 :
df_with_NAN.fillna(1)
df_with_NAN
选择性填充:
我们可以选择只对某些特定的行或者列进行填充。比如只对 'A' 列进行操作,在空值处填入该列的平均值:
df_with_NAN['A'].fillna(df_with_NAN['A'].mean())
df_with_NAN
同理,.dropna() 和 .fillna() 并不会永久性改变你的数据,除非你传入了inplace=True 参数。