数据操作主要包括,数据存取、数据切片及数据运算三部分。
5.4.1 数据存取
Pandas支持如下数据文件的读取存取,方便快捷的数据操作是Pandas库的一大优势。各种数据文件格式及对应的存取函数,如下表所示:
文件格式名 | 读取函数 | 写入函数 |
---|---|---|
Python字典数据 | pd.DataFrame(dict) | df.to_dict() |
Excel文档 | pd.read_excel(filename) | df.to_excel(filename) |
CSV文档 | pd.read_csv(filename) | df.to_csv(filename) |
分隔的文本文件(如TSV) | pd.read_table(filename) | |
SQL数据库文件 | pd.read_sql(query,connection_object) | df.to_sql(table_name,connection_object) |
JSON格式的字符串、URL或文件 | pd.read_json(json_string) | pd.to_json(filename) |
直接创建DataFrame对象
上一节创建的DataFrame对象,已引入了字典序列的值导入数据的方法,示例代码如下:
import pandas as pd
d={'one':pd.Series([1, 2, 3], index=['a', 'b', 'c']), 'two':pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
df.index.name="index"
print(df)
运行结果:
one two
index
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
可以看到,d是一个字典,其中one的值为Series有3个值,而two为Series有4个值。由d构建的为一个4行2列的DataFrame,并且将索引命名为index,其中one只有3个值,因此d行one列为NaN,即Not a Number,这是Pandas默认的缺失标记。
DataFrame也可以转换回字典类型,示例代码:
df.to_dict()
运行结果:
{'one': {'a': 1.0, 'b': 2.0, 'c': 3.0, 'd': nan},
'two': {'a': 1, 'b': 2, 'c': 3, 'd': 4}}
从Excel中存取数据
以上通过指令直接创建DataFrame,日常中大部分是从文件数据库中导入数据创建DataFrame。首先从Excel文件中读入DataFrame,示例代码:
df2 = pd.read_excel("abc.xls")
df2.head()
运行结果:
abc.xls是文件的相对路径名称,也可以采用绝对路径的方式,其参数为"d:/ml/abc.xls"。除了可以从Excel读取文件,我们也可以将DataFrame写入到Excel文件中,示例代码:
df2.to_excel("foo1.xlsx", sheet_name='sheet1')
以上代码中,参数sheet_name的值确定了将DataFrame表格数据导入在foo1.xlsx文件的sheet1表中,其foo1.xlsx文件放置在与iPython脚本编辑文件同一个目录中,如图所示:
foo1.xlsx文件路径从CSV中存取数据
CSV文件就是用逗号分隔的数据文件,其导入函数为read_csv(),括号内参数为CSV文件名,此时CSV文件与iPython脚本文件处于同一路径;参数也可以采用绝对路径的方式导入CSV文件,示例代码:
df3 = pd.read_csv("d:\ml\titanic_train.csv")
print(df3.head())
运行结果:
PassengerId Survived Pclass \
0 1 0 3
1 2 1 1
2 3 1 3
3 4 1 1
4 5 0 3
Name Sex Age SibSp \
0 Braund, Mr. Owen Harris male 22.0 1
1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1
2 Heikkinen, Miss. Laina female 26.0 0
3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1
4 Allen, Mr. William Henry male 35.0 0
Parch Ticket Fare Cabin Embarked
0 0 A/5 21171 7.2500 NaN S
1 0 PC 17599 71.2833 C85 C
2 0 STON/O2. 3101282 7.9250 NaN S
3 0 113803 53.1000 C123 S
4 0 373450 8.0500 NaN S
titanic_train.csv文件放置在D盘ml文件夹中,所以采用绝对路径方式读取数据,参数即"d:/ml/titanic_train.csv"。由于数据列名较多,所以采用多块显示的方式,将前5行数据以不同属性分块展现。
也可以将DataFrame对象写入CSV文件中,示例代码:
df3.to_csv("d:/ml/foo2.csv")
读取SQL数据库
pd.read_sql(query,connection_object)函数通过SQL查询语句读取数据库中的表格数据,其中第一个参数query是SQL查询语句,而第二个参数connection_object是python语言与相关数据库的连接资源接口文件。示例代码:
from sqlalchemy import create_engine
engine = create_engine("sqlite:///:memory:")
df4 = pd.read_sql("SELECT * FROM my_table", engine)
也可以将创建的df4对象导入到SQL数据库文件中,示例代码:
pd.to_sql("df4", engine)
以上介绍了几个常用数据文件的导入方法,其他函数与之类似,可以通过help()函数获取详细的数据文件存取方法,这里不再赘述。
5.4.2 数据切片
指定列
刚才通过导入数据文件或Python字典序列创建了DataFrame对象,下面我们将操作DataFrame对象中的数据,即介绍数据的切片与筛选命令。首先选择其中的一列,示例代码:
df["one"]
运行结果:
index
a 1.0
b 2.0
c 3.0
d NaN
Name: one, dtype: float64
显示的结果相当于一个Series,保留其索引号a、b、c、d,以及显示one列的所有值。我们也可以使用df.one的命令得到相同的结果。示例代码:
df.one
运行结果
index
a 1.0
b 2.0
c 3.0
d NaN
Name: one, dtype: float64
此外,可以通过list列表参数,返回多个属性列的值,示例代码:
df[["one", "two"]]
运行结果:
one two
index
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
由于原DataFrame仅有两列元素数据,因此返回的结果与原DataFrame对象相同。
指定行
如果要指定DataFrame对象的前三行记录,可以用切片命令,示例代码:
print(df[0:3])
运行结果:
one two
index
a 1.0 1
b 2.0 2
c 3.0 3
此结果返回的依旧是一个DataFrame对象,即以多个属性列表格。我们也可以使用起始索引名称和结束索引名称进行切片操作,注意其结果包含结束索引的数据,示例代码:
print(df['a' : 'b'])
运行结果:
one two
index
a 1.0 1
b 2.0 2
loc方法
通过DataFrame的loc方法(location的缩写)通过标签进行切片,即指定行列标签选取数据,操作格式为df.iloc[行标签, 列标签],示例代码:
df.loc['a':'c',"one"]
运行结果:
index
a 1.0
b 2.0
c 3.0
Name: one, dtype: float64
其中,df.loc的第一个参数为行标签(必须是指定的索引号,不能是数字),第二个参数为列标签(可选参数,默认为所有列标签)。两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回是DataFrame,否则为Series。
iloc方法
我们也可以通过DataFrame的iloc方法通过位置选取数据,功能与loc类似,需要注意的是iloc是integer & location的缩写,即只能以数字为索引号进行切片操作,操作格式为df.iloc[行位置, 列位置],示例代码:
print(df.iloc[1,1]) #选取第二行、第二列的值,返回的为单个值
print("----------------------")
print(df.iloc[[0,2], :]) #选取第一行及第三行的数据
print("----------------------")
print(df.iloc[0:2, :]) #选取第一行到第三行(不包含)的数据
print("----------------------")
print(df.iloc[:, 1]) #选取所有记录的第一列的值,返回的为一个Series
print("----------------------")
print(df.iloc[1, :]) #选取第一行数据,返回的为一个Series
运行结果:
2.0
----------------------
one two
index
a 1.0 1
c 3.0 3
----------------------
one two
index
a 1.0 1
b 2.0 2
----------------------
index
a 1
b 2
c 3
d 4
Name: two, dtype: int64
----------------------
one 2.0
two 2.0
Name: b, dtype: float64
ix方法
除了loc和iloc,更广义的切片方式是使用ix,它根据给定的索引类型自行判断是使用位置还是标签进行切片。操作格式为df.iloc[行位置(或行标签), 列位置(或列标签)],示例代码:
print(df.ix[1, 1])
print("----------------------")
print(df.ix['a':'b', 0])
运行结果:
2.0
----------------------
index
a 1.0
b 2.0
Name: one, dtype: float64
逻辑切片
通过逻辑指针进行数据切片,操作格式为df[逻辑条件],示例代码:
print(df[df.one >= 2]) #单个逻辑条件
print("----------------------")
print(df[df['one']>=2]) #结果与上面命令等价
print("----------------------")
print(df[(df.one >= 1) & (df.one < 3)]) #多个逻辑条件
运行结果:
one two
index
b 2.0 2
c 3.0 3
----------------------
one two
index
b 2.0 2
c 3.0 3
----------------------
one two
index
a 1.0 1
b 2.0 2
此外可以添加列标签参数,对逻辑条件指定的结果进行列选择,示例代码:
print(df[df.one>2]['two'])
运行结果:
index
b 2
c 3
Name: two, dtype: int64
5.4.3 数据运算
基本运算符运算
DataFrame对象可以对若干列值进行基本运算,其运算方式是每一行记录之间的列值的基本运算操作,可以将结果返回生成新的列值,示例代码:
df["three"] = df["one"]*10 + df["two"] #将one列的所有值乘以10倍后与同行的two列的所有值进行相加运算
df.head()
运行结果:
one two three
index
a 1.0 1 11.0
b 2.0 2 22.0
c 3.0 3 33.0
d NaN 4 NaN
由结果可以看出NaN值对四则运算规则没有意义,其结果依旧是NaN。
数值运算函数
Series和DataFrame对象都支持NumPy的数组接口,因此可以直接使用NumPy提供的ufunc函数对它们进行运算。例如add()、sub()、mul()、div()、mod()等与二元运算符对应的函数。此外,这些函数可以通过axis、level和fill_value等参数控制其运算行为。为演示运算函数中遇到的特殊情况处理,我们首先创建一个DataFrame和两个Series对象,示例代码:
df = pd.DataFrame(np.random.randint(0,10,(5,4)),index=['a','b','c','d','e'])
s1 = pd.Series(np.random.randint(0,10,5),index=['a','b','c','d','e'])
s2 = pd.Series([7,-2,3,5],index=['a','c','d','e'])
print(df)
print('\n')
print(s1)
print('\n')
print(s2)
运行结果:
0 1 2 3
a 5 5 7 0
b 7 9 5 5
c 0 6 2 4
d 0 0 6 5
e 1 5 5 4
a 4
b 8
c 4
d 9
e 2
dtype: int32
a 7
c -2
d 3
e 5
dtype: int64
由结果可知,创建一个5行4列的DataFrame,其中相应的行标索引号分别为字母abcde,而针对Series对象,分别创建了行标索引为abcde的s1序列和行标索引为acde的s2序列。我们可以直接采用两序列相加的方式,并将结果赋值于新的序列s3,示例代码:
s3=s1+s2
print(s3)
运行结果:
a 8.0
b NaN
c 6.0
d 10.0
e 10.0
dtype: float64
由于s2序列中没有b行索引下标,所以运算结果s3的b行记录用NaN补全。而通过运算函数里fill_value参数值的设置,我们可以对缺失值进行自动补全,示例代码:
print(s1.add(s3, fill_value=0)) #加,将缺失值设置为0
print("\n")
print(s1.sub(s3,fill_value=2)) #减,将缺失值设置为2
print("\n")
print(s1.mul(s3,fill_value=3)) #乘,将缺失值设置为3
print("\n")
print(s1.div(s3,fill_value=4)) #除,将缺失值设置为4
运行结果:
a 9.0
b 5.0
c 14.0
d 17.0
e 15.0
dtype: float64
a -7.0
b 3.0
c 2.0
d -3.0
e -5.0
dtype: float64
a 8.0
b 15.0
c 48.0
d 70.0
e 50.0
dtype: float64
a 0.125000
b 1.250000
c 1.333333
d 0.700000
e 0.500000
dtype: float64
数值统计函数
Pandas提供各种统计运算方法,如sum()、cumsum()、max()、min()、idxmin()、idxmax()、describe()、mean()、median()、std()等,这些函数都有如下三个常用参数:
- axis:指定运算对应的轴
- level:指定运算对应的索引级别
- skipna:运算是否自动跳过NaN
示例代码:
data = {'Country' : ['Belgium', 'India', 'Brazil'], 'Capital' : ['Brussels', 'New Delhi', 'Brasilia'], 'Population' : [11190846, 1303171035, 207847528] }
df = pd.DataFrame(data, columns = ['Country', 'Capital', 'Population']) #生成名为df的DataFrame对象
print("sum:",df.sum()) #对每列值求和
print("\n")
print("cumsum:",df.cumsum()) #返回每列值对行进行的累加和
print("\n")
print("min:",df.min()) #返回每列最小值
print("\n")
print("max:",df.max()) #返回每列最大值
print("\n")
print("describe:",df.describe()) #获取数据集的常用统计量信息
print("\n")
print("mean:",df.mean()) #返回每列均值
print("\n")
print("median:",df.median()) #返回每列中位数值
print("\n")
print("standard:",df.std()) #返回每列标准差值
运行结果
sum: Country BelgiumIndiaBrazil
Capital BrusselsNew DelhiBrasilia
Population 1522209409
dtype: object
cumsum: Country Capital Population
0 Belgium Brussels 11190846
1 BelgiumIndia BrusselsNew Delhi 1314361881
2 BelgiumIndiaBrazil BrusselsNew DelhiBrasilia 1522209409
min: Country Belgium
Capital Brasilia
Population 11190846
dtype: object
max: Country India
Capital New Delhi
Population 1303171035
dtype: object
describe: Population
count 3.000000e+00
mean 5.074031e+08
std 6.961346e+08
min 1.119085e+07
25% 1.095192e+08
50% 2.078475e+08
75% 7.555093e+08
max 1.303171e+09
mean: Population 5.074031e+08
dtype: float64
median: Population 207847528.0
dtype: float64
standard: Population 6.961346e+08
dtype: float64
注意,在以上返回结果中,describe()、mean()、median()和std()函数,仅对数值类型数据有效。此外,可以添加参数分别针对行列值进行数值统计,示例代码:
df = pd.DataFrame(np.random.randint(0,10,(5,4)),index=['a','b','c','d','e'])
print(df.mean())
print('\n')
print(df.mean(0))
print('\n')
print(df.mean(1))
运行结果:
0 5.2
1 5.4
2 4.8
3 5.4
dtype: float64
0 5.2
1 5.4
2 4.8
3 5.4
dtype: float64
a 6.00
b 4.75
c 4.75
d 6.00
e 4.50
dtype: float64
以上结果,不带参数或参数为0均返回的是每列的均值,而参数为1返回每行均值。由此说明mean()函数的默认参数就是0,即对每列进行均值统计分析,而当参数为1时则针对每行进行均值统计分析。此种参数的设置,对其他统计函数依然有效。
排序操作
DataFrame提供多种排序方式,主要介绍sort_index()、sort_values()和sort()方法。示例代码:
df = pd.DataFrame(np.random.randint(0,10,(5,4)),columns=['a','b','c','d'])
print(df)
print('\n')
print(df.sort_index(axis=1,ascending=False))
print('\n')
print(df.sort_values(by='a',ascending=True))
运行结果
a b c d
0 4 2 8 6
1 8 2 3 2
2 1 8 6 7
3 8 6 9 6
4 3 3 5 4
d c b a
0 6 8 2 4
1 2 3 2 8
2 7 6 8 1
3 6 9 6 8
4 4 5 3 3
a b c d
2 1 8 6 7
4 3 3 5 4
0 4 2 8 6
1 8 2 3 2
3 8 6 9 6
sort_index()方法以轴的标签进行排序。axis是指用于排序的轴,可选的值有0和1,默认为0即行标签(Y轴),1为按照列标签排序。ascending是排序方式,默认为True即升序排列。sort_values()方法,顾名思义,是按照数据值进行排序,在上例中的参数by即按照a列的值进行升序排列。
sort()方法与sort_values()方法类似,根据需要按照指定列进行排序,可以仅指定一个列作为排序标准(以单独列名作为columns的参数),也可以进行多重排序(columns的参数为一个列名的List,列名的出现顺序决定排序中的优先级),在多重排序中ascending参数也为一个List,分别于columns中的List元素对应。示例代码:
print(df.sort(columns='b', ascending=False)) #按照b列的降序排列
print('\n')
print(df.sort(columns=['a','c'], ascending=[False,True])) #首先按照a列的降序,然后按照c列的升序排列
print('\n')
print(df.sort(columns=['a','c'], ascending=[0,1])) #False可以用0,True可以用1替换
运行结果
a b c d
2 1 8 6 7
3 8 6 9 6
4 3 3 5 4
0 4 2 8 6
1 8 2 3 2
a b c d
1 8 2 3 2
3 8 6 9 6
0 4 2 8 6
4 3 3 5 4
2 1 8 6 7
a b c d
1 8 2 3 2
3 8 6 9 6
0 4 2 8 6
4 3 3 5 4
2 1 8 6 7
字符操作
Pandas除了可以对数值数据进行操作,也提供了字符串操作方法str,示例代码:
data = {'Country' : ['Belgium', 'India', 'Brazil'], 'Capital' : ['Brussels', 'New Delhi', 'Brasilia'], 'Population' : [11190846, 1303171035, 207847528] }
df = pd.DataFrame(data, columns = ['Country', 'Capital', 'Population'])
df.['Country'].str.upper() #将字符转换为大写
df.['Country'].str.len() #求字符长度
df.['Country'].str.coutains('a') #coutains参数可以是字符或字符串,即判断字符串是否包含参数中的字符
字符的操作方法还有很多,可以查阅相关文档,这里不做赘述。
网友评论