数据科学 IPython 笔记本 7.1 Pandas

2022-07-11 14:42:06 浏览数 (1)

7.1 Pandas

原文:Pandas 译者:飞龙 协议:CC BY-NC-SA 4.0 致谢:这个笔记摘自 Wes McKinney 的著作 《Python 数据分析》(Python for Data Analysis)

  • 序列(Series
  • 数据帧(DataFrame
  • 重索引
  • 删除条目
  • 索引,选择和过滤
  • 算术和数据对齐
  • 函数应用和映射
  • 排序和排名
  • 带有重复值的轴索引
  • 汇总和计算描述性统计量
  • 清洗数据(构建中)
  • 输入和输出(构建中)
代码语言:javascript复制
from pandas import Series, DataFrame
import pandas as pd
import numpy as np

序列(Series

Series是一维数组对象,包含数据数组和相关的数据标签数组。数据可以是任何 NumPy 数据类型,标签是序列的索引。

创建Series

代码语言:javascript复制
ser_1 = Series([1, 1, 2, -3, -5, 8, 13])
ser_1

'''
0     1
1     1
2     2
3    -3
4    -5
5     8
6    13
dtype: int64
'''

获取Series的数组表示:

代码语言:javascript复制
ser_1.values

# array([ 1,  1,  2, -3, -5,  8, 13])

Series对象是不可变的,并持有轴标签和元数据,如名称和轴名称。

获取Series的索引:

代码语言:javascript复制
ser_1.index

# Int64Index([0, 1, 2, 3, 4, 5, 6], dtype='int64')

使用自定义索引创建Series

代码语言:javascript复制
ser_2 = Series([1, 1, 2, -3, -5], index=['a', 'b', 'c', 'd', 'e'])
ser_2

'''
a    1
b    1
c    2
d   -3
e   -5
dtype: int64
'''

Series获取值:

代码语言:javascript复制
ser_2[4] == ser_2['e']

# True

通过传入列表从Series获取一组值:

代码语言:javascript复制
ser_2[['c', 'a', 'b']]

'''
c    2
a    1
b    1
dtype: int64
'''

获取大于 0 的值:

代码语言:javascript复制
ser_2[ser_2 > 0]

'''
a    1
b    1
c    2
dtype: int64
'''

标量乘法:

代码语言:javascript复制
ser_2 * 2

'''
a     2
b     2
c     4
d    -6
e   -10
dtype: int64
'''

应用 NumPy 数学函数:

代码语言:javascript复制
import numpy as np
np.exp(ser_2)

'''
a    2.718282
b    2.718282
c    7.389056
d    0.049787
e    0.006738
dtype: float64
'''

Series就像一个固定长度的有序字典。

传入字典来创建Series

代码语言:javascript复制
dict_1 = {'foo' : 100, 'bar' : 200, 'baz' : 300}
ser_3 = Series(dict_1)
ser_3

'''
bar    200
baz    300
foo    100
dtype: int64
'''

通过传入索引来重排Series(未找到的索引是 NaN):

代码语言:javascript复制
index = ['foo', 'bar', 'baz', 'qux']
ser_4 = Series(dict_1, index=index)
ser_4

'''
foo    100
bar    200
baz    300
qux    NaN
dtype: float64
'''

使用 pandas 方法检查 NaN:

代码语言:javascript复制
pd.isnull(ser_4)

'''
foo    False
bar    False
baz    False
qux     True
dtype: bool
'''

使用Series的方法检查 NaN:

代码语言:javascript复制
ser_4.isnull()

'''
foo    False
bar    False
baz    False
qux     True
dtype: bool
'''

在算术运算中,Series自动对齐不同的索引数据:

代码语言:javascript复制
ser_3   ser_4

'''
bar    400
baz    600
foo    200
qux    NaN
dtype: float64
'''

命名Series

代码语言:javascript复制
ser_4.name = 'foobarbazqux'

命名Series索引:

代码语言:javascript复制
ser_4.index.name = 'label'

ser_4

'''
label
foo    100
bar    200
baz    300
qux    NaN
Name: foobarbazqux, dtype: float64
'''

原地重命名Series的索引:

代码语言:javascript复制
ser_4.index = ['fo', 'br', 'bz', 'qx']
ser_4

'''
fo    100
br    200
bz    300
qx    NaN
Name: foobarbazqux, dtype: float64
'''

数据帧(DataFrame

DataFrame是表格数据结构,包含列的有序集合。 每列可以是不同的类型。 DataFrame同时具有行索引和列索引,类似于Series的字典。行和列操作大致是对称实现的。 索引DataFrame时返回的列是底层数据的视图,而不是副本。 要获取副本,请使用Series的复制方法。

创建DataFrame:

代码语言:javascript复制
data_1 = {'state' : ['VA', 'VA', 'VA', 'MD', 'MD'],
          'year' : [2012, 2013, 2014, 2014, 2015],
          'pop' : [5.0, 5.1, 5.2, 4.0, 4.1]}
df_1 = DataFrame(data_1)
df_1

pop

state

year

0

5.0

VA

2012

1

5.1

VA

2013

2

5.2

VA

2014

3

4.0

MD

2014

4

4.1

MD

2015

指定列的序列来创建DataFrame

代码语言:javascript复制
df_2 = DataFrame(data_1, columns=['year', 'state', 'pop'])
df_2

| | year | state | pop | | — | — | — | | 0 | 2012 | VA | 5.0 | | 1 | 2013 | VA | 5.1 | | 2 | 2014 | VA | 5.2 | | 3 | 2014 | MD | 4.0 | | 4 | 2015 | MD | 4.1 |

Series类似,数据中不存在的列是 NaN:

代码语言:javascript复制
df_3 = DataFrame(data_1, columns=['year', 'state', 'pop', 'unempl'])
df_3

year

state

pop

unempl

0

2012

VA

5.0

NaN

1

2013

VA

5.1

NaN

2

2014

VA

5.2

NaN

3

2014

MD

4.0

NaN

4

2015

MD

4.1

NaN

通过键检索列,返回Series

代码语言:javascript复制
df_3['state']

'''
0    VA
1    VA
2    VA
3    MD
4    MD
Name: state, dtype: object
'''

通过属性检索列,返回Series

代码语言:javascript复制
df_3.year

'''
0    2012
1    2013
2    2014
3    2014
4    2015
Name: year, dtype: int64
'''

通过位置检索行:

代码语言:javascript复制
df_3.ix[0]

'''
year      2012
state       VA
pop          5
unempl     NaN
Name: 0, dtype: object
'''

通过复制来更新列:

代码语言:javascript复制
df_3['unempl'] = np.arange(5)
df_3

| | year | state | pop | unempl | | — | — | — | — | | 0 | 2012 | VA | 5.0 | 0 | | 1 | 2013 | VA | 5.1 | 1 | | 2 | 2014 | VA | 5.2 | 2 | | 3 | 2014 | MD | 4.0 | 3 | | 4 | 2015 | MD | 4.1 | 4 |

Series赋给列(请注意,如果指定了列表或数组,则长度必须与DataFrame匹配,与Series不同):

代码语言:javascript复制
unempl = Series([6.0, 6.0, 6.1], index=[2, 3, 4])
df_3['unempl'] = unempl
df_3

year

state

pop

unempl

0

2012

VA

5.0

NaN

1

2013

VA

5.1

NaN

2

2014

VA

5.2

6.0

3

2014

MD

4.0

6.0

4

2015

MD

4.1

6.1

对不存在的新列赋值来创建新列:

代码语言:javascript复制
df_3['state_dup'] = df_3['state']
df_3

year

state

pop

unempl

state_dup

0

2012

VA

5.0

NaN

VA

1

2013

VA

5.1

NaN

VA

2

2014

VA

5.2

6.0

VA

3

2014

MD

4.0

6.0

MD

4

2015

MD

4.1

6.1

MD

删除一列:

代码语言:javascript复制
del df_3['state_dup']
df_3

year

state

pop

unempl

0

2012

VA

5.0

NaN

1

2013

VA

5.1

NaN

2

2014

VA

5.2

6.0

3

2014

MD

4.0

6.0

4

2015

MD

4.1

6.1

从字典的嵌套字典创建DataFrame(如果没有指定显示索引,内部字典中的键,被合并并排序来形成结果中的索引):

代码语言:javascript复制
pop = {'VA' : {2013 : 5.1, 2014 : 5.2},
       'MD' : {2014 : 4.0, 2015 : 4.1}}
df_4 = DataFrame(pop)
df_4

MD

VA

2013

NaN

5.1

2014

4.0

5.2

2015

4.1

NaN

转置DataFrame:

代码语言:javascript复制
df_4.T

2013

2014

2015

MD

NaN

4.0

4.1

VA

5.1

5.2

NaN

Series的词典创建一个DataFrame

代码语言:javascript复制
data_2 = {'VA' : df_4['VA'][1:],
          'MD' : df_4['MD'][2:]}
df_5 = DataFrame(data_2)
df_5

MD

VA

2014

NaN

5.2

2015

4.1

NaN

设置DataFrame的索引名称:

代码语言:javascript复制
df_5.index.name = 'year'
df_5

MD

VA

year

2014

NaN

5.2

2015

4.1

NaN

设置DataFrame的列名称:

代码语言:javascript复制
df_5.columns.name = 'state'
df_5

state

MD

VA

year

2014

NaN

5.2

2015

4.1

NaN

DataFrame中包含的数据作为 2D ndarray返回:

代码语言:javascript复制
df_5.values

'''
array([[ nan,  5.2],
       [ 4.1,  nan]])
'''

如果列是不同的dtypes,则 2D 数组的dtype将兼容所有列:

代码语言:javascript复制
df_3.values

'''
array([[2012, 'VA', 5.0, nan],
       [2013, 'VA', 5.1, nan],
       [2014, 'VA', 5.2, 6.0],
       [2014, 'MD', 4.0, 6.0],
       [2015, 'MD', 4.1, 6.1]], dtype=object)
'''

重索引

使用符合新索引的数据创建新对象。任何缺失值都设置为 NaN。

代码语言:javascript复制
df_3

year

state

pop

unempl

0

2012

VA

5.0

NaN

1

2013

VA

5.1

NaN

2

2014

VA

5.2

6.0

3

2014

MD

4.0

6.0

4

2015

MD

4.1

6.1

行的重新索引将返回具有指定索引的新DataFrame

代码语言:javascript复制
df_3.reindex(list(reversed(range(0, 6))))

year

state

pop

unempl

5

NaN

NaN

NaN

NaN

4

2015

MD

4.1

6.1

3

2014

MD

4.0

6.0

2

2014

VA

5.2

6.0

1

2013

VA

5.1

NaN

0

2012

VA

5.0

NaN

缺失值可以设置为 NaN 以外的值:

代码语言:javascript复制
df_3.reindex(range(6, 0), fill_value=0)

year

state

pop

unempl

插入有序数据,如时间序列:

代码语言:javascript复制
ser_5 = Series(['foo', 'bar', 'baz'], index=[0, 2, 4])

ser_5.reindex(range(5), method='ffill')

'''
0    foo
1    foo
2    bar
3    bar
4    baz
dtype: object
'''

ser_5.reindex(range(5), method='bfill')

'''
0    foo
1    bar
2    bar
3    baz
4    baz
dtype: object
'''

重索引列:

代码语言:javascript复制
df_3.reindex(columns=['state', 'pop', 'unempl', 'year'])

state

pop

unempl

year

0

VA

5.0

NaN

2012

1

VA

5.1

NaN

2013

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

重新索引行和列,同时填充行:

代码语言:javascript复制
df_3.reindex(index=list(reversed(range(0, 6))),
             fill_value=0,
             columns=['state', 'pop', 'unempl', 'year'])

state

pop

unempl

year

5

0

0.0

0.0

0

4

MD

4.1

6.1

2015

3

MD

4.0

6.0

2014

2

VA

5.2

6.0

2014

1

VA

5.1

NaN

2013

0

VA

5.0

NaN

2012

使用ix的重索引:

代码语言:javascript复制
df_6 = df_3.ix[range(0, 7), ['state', 'pop', 'unempl', 'year']]
df_6

state

pop

unempl

year

0

VA

5.0

NaN

2012

1

VA

5.1

NaN

2013

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

5

NaN

NaN

NaN

NaN

6

NaN

NaN

NaN

NaN

删除条目

SeriesDataFrame中删除行:

代码语言:javascript复制
df_7 = df_6.drop([0, 1])
df_7

state

pop

unempl

year

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

5

NaN

NaN

NaN

NaN

6

NaN

NaN

NaN

NaN

DataFrame中删除列:

代码语言:javascript复制
df_7 = df_7.drop('unempl', axis=1)
df_7

state

pop

year

2

VA

5.2

2014

3

MD

4.0

2014

4

MD

4.1

2015

5

NaN

NaN

NaN

6

NaN

NaN

NaN

索引,选择和过滤

Series索引类似于 NumPy 数组索引,并且能够使用Series的索引值。

代码语言:javascript复制
ser_2

'''
a    1
b    1
c    2
d   -3
e   -5
dtype: int64
'''

Series中选择值:

代码语言:javascript复制
ser_2[0] == ser_2['a']

# True

Series中选择切片:

代码语言:javascript复制
ser_2[1:4]

'''
b    1
c    2
d   -3
dtype: int64
'''

Series中选择特定值:

代码语言:javascript复制
ser_2[['b', 'c', 'd']]

'''
b    1
c    2
d   -3
dtype: int64
'''

基于过滤器从Series中选择值:

代码语言:javascript复制
ser_2[ser_2 > 0]

'''
a    1
b    1
c    2
dtype: int64
'''

从带标签的Series中选择切片(注意包含终点):

代码语言:javascript复制
ser_2['a':'b']

'''
a    1
b    1
dtype: int64
'''

Series切片赋值(注意包含终点):

代码语言:javascript复制
ser_2['a':'b'] = 0
ser_2

'''
a    0
b    0
c    2
d   -3
e   -5
dtype: int64
'''

Pandas 支持DataFrame中的索引。

代码语言:javascript复制
df_6

state

pop

unempl

year

0

VA

5.0

NaN

2012

1

VA

5.1

NaN

2013

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

5

NaN

NaN

NaN

NaN

6

NaN

NaN

NaN

NaN

DataFrame中选择特定列:

代码语言:javascript复制
df_6[['pop', 'unempl']]

pop

unempl

0

5.0

NaN

1

5.1

NaN

2

5.2

6.0

3

4.0

6.0

4

4.1

6.1

5

NaN

NaN

6

NaN

NaN

DataFrame中选择切片:

代码语言:javascript复制
df_6[:2]

state

pop

unempl

year

0

VA

5.0

NaN

2012

1

VA

5.1

NaN

2013

基于过滤器从DataFrame中选择行:

代码语言:javascript复制
df_6[df_6['pop'] > 5]

state

pop

unempl

year

1

VA

5.1

NaN

2013

2

VA

5.2

6

2014

DataFrame上执行标量比较:

代码语言:javascript复制
df_6 > 5

state

pop

unempl

year

0

True

False

False

True

1

True

True

False

True

2

True

True

True

True

3

True

False

True

True

4

True

False

True

True

5

True

False

False

False

6

True

False

False

False

DataFrame上执行标量比较,保留满足过滤器的行:

代码语言:javascript复制
df_6[df_6 > 5]

state

pop

unempl

year

0

VA

NaN

NaN

2012

1

VA

5.1

NaN

2013

2

VA

5.2

6.0

2014

3

MD

NaN

6.0

2014

4

MD

NaN

6.1

2015

5

NaN

NaN

NaN

NaN

6

NaN

NaN

NaN

NaN

DataFrame中选择一行(注意包含终点):

代码语言:javascript复制
df_6.ix[2:3]

state

pop

unempl

year

2

VA

5.2

6

2014

3

MD

4.0

6

2014

DataFrame的特定列中选择行的切片:

代码语言:javascript复制
df_6.ix[0:2, 'pop']

'''
0    5.0
1    5.1
2    5.2
Name: pop, dtype: float64
'''

根据特定行上的算术运算选择行:

代码语言:javascript复制
df_6.ix[df_6.unempl > 5.0]

state

pop

unempl

year

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

算术和数据对齐

如果索引对不相同,则将Series对象相加会产生索引对的并集,使不重叠的索引为 NaN:

代码语言:javascript复制
np.random.seed(0)
ser_6 = Series(np.random.randn(5),
               index=['a', 'b', 'c', 'd', 'e'])
ser_6

'''
a    1.764052
b    0.400157
c    0.978738
d    2.240893
e    1.867558
dtype: float64
'''

np.random.seed(1)
ser_7 = Series(np.random.randn(5),
               index=['a', 'c', 'e', 'f', 'g'])
ser_7

'''
a    1.624345
c   -0.611756
e   -0.528172
f   -1.072969
g    0.865408
dtype: float64
'''

ser_6   ser_7

'''
a    3.388398
b         NaN
c    0.366982
d         NaN
e    1.339386
f         NaN
g         NaN
dtype: float64
'''

为不重叠的索引设置填充值而不是 NaN:

代码语言:javascript复制
ser_6.add(ser_7, fill_value=0)

'''
a    3.388398
b    0.400157
c    0.366982
d    2.240893
e    1.339386
f   -1.072969
g    0.865408
dtype: float64
'''

如果索引对不相同,则将DataFrame对象相加,会产生行和列的索引对的并集,使不重叠的索引为 NaN:

代码语言:javascript复制
np.random.seed(0)
df_8 = DataFrame(np.random.rand(9).reshape((3, 3)),
                 columns=['a', 'b', 'c'])
df_8

a

b

c

0

0.548814

0.715189

0.602763

1

0.544883

0.423655

0.645894

2

0.437587

0.891773

0.963663

代码语言:javascript复制
np.random.seed(1)
df_9 = DataFrame(np.random.rand(9).reshape((3, 3)),
                 columns=['b', 'c', 'd'])
df_9

b

c

d

0

0.417022

0.720324

0.000114

1

0.302333

0.146756

0.092339

2

0.186260

0.345561

0.396767

代码语言:javascript复制
df_8   df_9

a

b

c

d

0

NaN

1.132211

1.323088

NaN

1

NaN

0.725987

0.792650

NaN

2

NaN

1.078033

1.309223

NaN

为不重叠的索引设置填充值而不是 NaN:

代码语言:javascript复制
df_10 = df_8.add(df_9, fill_value=0)
df_10

a

b

c

d

0

0.548814

1.132211

1.323088

0.000114

1

0.544883

0.725987

0.792650

0.092339

2

0.437587

1.078033

1.309223

0.396767

与 NumPy 一样,pandas 支持DataFrameSeries之间的算术运算。

DataFrame的列上匹配Series的索引,并向下广播行:

代码语言:javascript复制
ser_8 = df_10.ix[0]
df_11 = df_10 - ser_8
df_11

a

b

c

d

0

0.000000

0.000000

0.000000

0.000000

1

-0.003930

-0.406224

-0.530438

0.092224

2

-0.111226

-0.054178

-0.013864

0.396653

DataFrame的列上匹配Series的索引,向下广播行并合并不匹配的索引:

代码语言:javascript复制
ser_9 = Series(range(3), index=['a', 'd', 'e'])
ser_9

'''
a    0
d    1
e    2
dtype: int64
'''

df_11 - ser_9

a

b

c

d

e

0

0.000000

NaN

NaN

-1.000000

NaN

1

-0.003930

NaN

NaN

-0.907776

NaN

2

-0.111226

NaN

NaN

-0.603347

NaN

使用算术方法,在列上广播并匹配行(axis = 0):

代码语言:javascript复制
df_10

a

b

c

d

0

0.548814

1.132211

1.323088

0.000114

1

0.544883

0.725987

0.792650

0.092339

2

0.437587

1.078033

1.309223

0.396767

代码语言:javascript复制
ser_10 = Series([100, 200, 300])
ser_10

'''
0    100
1    200
2    300
dtype: int64
'''

df_10.sub(ser_10, axis=0)

a

b

c

d

0

-99.451186

-98.867789

-98.676912

-99.999886

1

-199.455117

-199.274013

-199.207350

-199.907661

2

-299.562413

-298.921967

-298.690777

-299.603233

函数应用和映射

NumPy ufunc(逐元素数组方法)能够操作 pandas 对象:

代码语言:javascript复制
df_11 = np.abs(df_11)
df_11

a

b

c

d

0

0.000000

0.000000

0.000000

0.000000

1

0.003930

0.406224

0.530438

0.092224

2

0.111226

0.054178

0.013864

0.396653

将 1D 数组上的函数应用于每列:

代码语言:javascript复制
func_1 = lambda x: x.max() - x.min()
df_11.apply(func_1)

'''
a    0.111226
b    0.406224
c    0.530438
d    0.396653
dtype: float64
'''

将 1D 数组上的函数应用于每行:

代码语言:javascript复制
df_11.apply(func_1, axis=1)

'''
0    0.000000
1    0.526508
2    0.382789
dtype: float64
'''

应用函数并返回DataFrame:

代码语言:javascript复制
func_2 = lambda x: Series([x.min(), x.max()], index=['min', 'max'])
df_11.apply(func_2)

a

b

c

d

min

0.000000

0.000000

0.000000

0.000000

max

0.111226

0.406224

0.530438

0.396653

将逐元素的 Python 函数应用于DataFrame

代码语言:javascript复制
func_3 = lambda x: '%.2f' %x
df_11.applymap(func_3)

a

b

c

d

0

0.00

0.00

0.00

0.00

1

0.00

0.41

0.53

0.09

2

0.11

0.05

0.01

0.40

将逐元素的 Python 函数应用于Series

代码语言:javascript复制
df_11['a'].map(func_3)

'''
0    0.00
1    0.00
2    0.11
Name: a, dtype: object
'''

排序和排名

代码语言:javascript复制
ser_4

'''
fo    100
br    200
bz    300
qx    NaN
Name: foobarbazqux, dtype: float64
'''

按照索引排序Series

代码语言:javascript复制
ser_4.sort_index()

'''
br    200
bz    300
fo    100
qx    NaN
Name: foobarbazqux, dtype: float64
'''

按照值排序Series

代码语言:javascript复制
ser_4.sort_values()

'''
fo    100
br    200
bz    300
qx    NaN
Name: foobarbazqux, dtype: float64
'''

df_12 = DataFrame(np.arange(12).reshape((3, 4)),
                  index=['three', 'one', 'two'],
                  columns=['c', 'a', 'b', 'd'])
df_12

c

a

b

d

three

0

1

2

3

one

4

5

6

7

two

8

9

10

11

按照索引排序DaraFrame

代码语言:javascript复制
df_12.sort_index()

c

a

b

d

one

4

5

6

7

three

0

1

2

3

two

8

9

10

11

按列倒序排序DaraFrame

代码语言:javascript复制
df_12.sort_index(axis=1, ascending=False)

d

c

b

a

three

3

0

2

1

one

7

4

6

5

two

11

8

10

9

按列排序DaraFrame的值:

代码语言:javascript复制
df_12.sort_values(by=['d', 'c'])

c

a

b

d

three

0

1

2

3

one

4

5

6

7

two

8

9

10

11

排名类似于numpy.argsort,除了通过为每个组分配平均排名来打破关系:

代码语言:javascript复制
ser_11 = Series([7, -5, 7, 4, 2, 0, 4, 7])
ser_11 = ser_11.sort_values()
ser_11

'''
1   -5
5    0
4    2
3    4
6    4
0    7
2    7
7    7
dtype: int64
'''

ser_11.rank()

'''
1    1.0
5    2.0
4    3.0
3    4.5
6    4.5
0    7.0
2    7.0
7    7.0
dtype: float64
'''

根据数据出现在Series中的位置,来排名Series

代码语言:javascript复制
ser_11.rank(method='first')

'''
1    1
5    2
4    3
3    4
6    5
0    6
2    7
7    8
dtype: float64
'''

使用分组的最大排名,降序排列Series

代码语言:javascript复制
ser_11.rank(ascending=False, method='max')

'''
1    8
5    7
4    6
3    5
6    5
0    3
2    3
7    3
dtype: float64
'''

DataFrame可以按行或列排名。

代码语言:javascript复制
df_13 = DataFrame({'foo' : [7, -5, 7, 4, 2, 0, 4, 7],
                   'bar' : [-5, 4, 2, 0, 4, 7, 7, 8],
                   'baz' : [-1, 2, 3, 0, 5, 9, 9, 5]})
df_13

bar

baz

foo

0

-5

-1

7

1

4

2

-5

2

2

3

7

3

0

0

4

4

4

5

2

5

7

9

0

6

7

9

4

7

8

5

7

在行上(按列)排名DataFrame

代码语言:javascript复制
df_13.rank()

bar

baz

foo

0

1.0

1.0

7.0

1

4.5

3.0

1.0

2

3.0

4.0

7.0

3

2.0

2.0

4.5

4

4.5

5.5

3.0

5

6.5

7.5

2.0

6

6.5

7.5

4.5

7

8.0

5.5

7.0

在列上(按行)排名DataFrame

代码语言:javascript复制
df_13.rank(axis=1)

bar

baz

foo

0

1.0

2.0

3

1

3.0

2.0

1

2

1.0

2.0

3

3

1.5

1.5

3

4

2.0

3.0

1

5

2.0

3.0

1

6

2.0

3.0

1

7

3.0

1.0

2

带有重复值的轴索引

标签在 Pandas 中不一定是唯一的:

代码语言:javascript复制
ser_12 = Series(range(5), index=['foo', 'foo', 'bar', 'bar', 'baz'])
ser_12

'''
foo    0
foo    1
bar    2
bar    3
baz    4
dtype: int64
'''

ser_12.index.is_unique

# False

选择序列的元素:

代码语言:javascript复制
ser_12['foo']

'''
foo    0
foo    1
dtype: int64
'''

选择DataFrame的元素:

代码语言:javascript复制
df_14 = DataFrame(np.random.randn(5, 4),
                  index=['foo', 'foo', 'bar', 'bar', 'baz'])
df_14

0

1

2

3

foo

-2.363469

1.135345

-1.017014

0.637362

foo

-0.859907

1.772608

-1.110363

0.181214

bar

0.564345

-0.566510

0.729976

0.372994

bar

0.533811

-0.091973

1.913820

0.330797

baz

1.141943

-1.129595

-0.850052

0.960820

代码语言:javascript复制
df_14.ix['bar']

0

1

2

3

bar

0.564345

-0.566510

0.729976

0.372994

bar

0.533811

-0.091973

1.913820

0.330797

汇总和计算描述性统计量

与 NumPy 数组不同,Pandas 描述性统计量会自动排除缺失数据。 除非整行或列为 NA,否则将排除 NaN 值。

代码语言:javascript复制
df_6

state

pop

unempl

year

0

VA

5.0

NaN

2012

1

VA

5.1

NaN

2013

2

VA

5.2

6.0

2014

3

MD

4.0

6.0

2014

4

MD

4.1

6.1

2015

5

NaN

NaN

NaN

NaN

6

NaN

NaN

NaN

NaN

代码语言:javascript复制
df_6.sum()

'''
pop          23.4
unempl       18.1
year      10068.0
dtype: float64
'''

按行求和:

代码语言:javascript复制
df_6.sum(axis=1)

'''
0    2017.0
1    2018.1
2    2025.2
3    2024.0
4    2025.2
5       0.0
6       0.0
dtype: float64
'''

计入 NaN:

代码语言:javascript复制
df_6.sum(axis=1, skipna=False)

'''
0       NaN
1       NaN
2    2025.2
3    2024.0
4    2025.2
5       NaN
6       NaN
dtype: float64
'''

清洗数据(构建中)

  • 替换
  • 删除
  • 连接
代码语言:javascript复制
from pandas import Series, DataFrame
import pandas as pd

创建DataFrame

代码语言:javascript复制
data_1 = {'state' : ['VA', 'VA', 'VA', 'MD', 'MD'],
          'year' : [2012, 2013, 2014, 2014, 2015],
          'population' : [5.0, 5.1, 5.2, 4.0, 4.1]}
df_1 = DataFrame(data_1)
df_1

population

state

year

0

5.0

VA

2012

1

5.1

VA

2013

2

5.2

VA

2014

3

4.0

MD

2014

4

4.1

MD

2015

替换

将字符串的所有出现替换为另一个字符串(不复制):

代码语言:javascript复制
df_1.replace('VA', 'VIRGINIA', inplace=True)
df_1

population

state

year

0

5.0

VIRGINIA

2012

1

5.1

VIRGINIA

2013

2

5.2

VIRGINIA

2014

3

4.0

MD

2014

4

4.1

MD

2015

在指定的列中,将字符串的所有出现替换为另一个字符串(不复制):

代码语言:javascript复制
df_1.replace({'state' : { 'MD' : 'MARYLAND' }}, inplace=True)
df_1

population

state

year

0

5.0

VIRGINIA

2012

1

5.1

VIRGINIA

2013

2

5.2

VIRGINIA

2014

3

4.0

MARYLAND

2014

4

4.1

MARYLAND

2015

删除

删除'population'列并返回DataFrame的副本:

代码语言:javascript复制
df_2 = df_1.drop('population', axis=1)
df_2

state

year

0

VIRGINIA

2012

1

VIRGINIA

2013

2

VIRGINIA

2014

3

MARYLAND

2014

4

MARYLAND

2015

连接

连接两个DaraFrame

代码语言:javascript复制
data_2 = {'state' : ['NY', 'NY', 'NY', 'FL', 'FL'],
          'year' : [2012, 2013, 2014, 2014, 2015],
          'population' : [6.0, 6.1, 6.2, 3.0, 3.1]}
df_3 = DataFrame(data_2)
df_3

population

state

year

0

6.0

NY

2012

1

6.1

NY

2013

2

6.2

NY

2014

3

3.0

FL

2014

4

3.1

FL

2015

代码语言:javascript复制
df_4 = pd.concat([df_1, df_3])
df_4

population

state

year

0

5.0

VIRGINIA

2012

1

5.1

VIRGINIA

2013

2

5.2

VIRGINIA

2014

3

4.0

MARYLAND

2014

4

4.1

MARYLAND

2015

0

6.0

NY

2012

1

6.1

NY

2013

2

6.2

NY

2014

3

3.0

FL

2014

4

3.1

FL

2015

输入和输出(构建中)

代码语言:javascript复制
from pandas import Series, DataFrame
import pandas as pd

将 CSV 文件中的数据读入DataFrame(对 TSV 使用sep='t'):

代码语言:javascript复制
df_1 = pd.read_csv("../data/ozone.csv")

获取DataFrame的摘要:

代码语言:javascript复制
df_1.describe()

Ozone

Solar.R

Wind

Temp

Month

Day

count

116.000000

146.000000

153.000000

153.000000

153.000000

153.000000

mean

42.129310

185.931507

9.957516

77.882353

6.993464

15.803922

std

32.987885

90.058422

3.523001

9.465270

1.416522

8.864520

min

1.000000

7.000000

1.700000

56.000000

5.000000

1.000000

25%

18.000000

115.750000

7.400000

72.000000

6.000000

8.000000

50%

31.500000

205.000000

9.700000

79.000000

7.000000

16.000000

75%

63.250000

258.750000

11.500000

85.000000

8.000000

23.000000

max

168.000000

334.000000

20.700000

97.000000

9.000000

31.000000

列出DataFrame的前五行:

代码语言:javascript复制
df_1.head()

Ozone

Solar.R

Wind

Temp

Month

Day

0

41

190

7.4

67

5

1

1

36

118

8.0

72

5

2

2

12

149

12.6

74

5

3

3

18

313

11.5

62

5

4

4

NaN

NaN

14.3

56

5

5

创建 CSV 文件的副本,以 UTF-8 编码并隐藏索引和标题标签:

代码语言:javascript复制
df_1.to_csv('../data/ozone_copy.csv', 
            encoding='utf-8', 
            index=False, 
            header=False)

查看数据目录:

代码语言:javascript复制
!ls -l ../data/

'''
total 1016
-rw-r--r--   1 donnemartin  staff  437903 Jul  7  2015 churn.csv
-rwxr-xr-x   1 donnemartin  staff   72050 Jul  7  2015 confusion_matrix.png
-rw-r--r--   1 donnemartin  staff    2902 Jul  7  2015 ozone.csv
-rw-r--r--   1 donnemartin  staff    3324 Apr  1 07:18 ozone_copy.csv
drwxr-xr-x  10 donnemartin  staff     340 Jul  7  2015 titanic
'''

0 人点赞