数据科学 IPython 笔记本 7.1 Pandas

7.1 Pandas

原文:Pandas

译者:飞龙

协议:CC BY-NC-SA 4.0

致谢:这个笔记摘自 Wes McKinney 的著作 《Python 数据分析》(Python for Data Analysis)

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

序列(Series

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

创建Series

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的数组表示:

ser_1.values

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

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

获取Series的索引:

ser_1.index

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

使用自定义索引创建Series

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获取值:

ser_2[4] == ser_2['e']

# True

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

ser_2[['c', 'a', 'b']]

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

获取大于 0 的值:

ser_2[ser_2 > 0]

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

标量乘法:

ser_2 * 2

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

应用 NumPy 数学函数:

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

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):

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:

pd.isnull(ser_4)

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

使用Series的方法检查 NaN:

ser_4.isnull()

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

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

ser_3 + ser_4

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

命名Series

ser_4.name = 'foobarbazqux'

命名Series索引:

ser_4.index.name = 'label'

ser_4

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

原地重命名Series的索引:

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:

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

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:

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

df_3['state']

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

通过属性检索列,返回Series

df_3.year

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

通过位置检索行:

df_3.ix[0]

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

通过复制来更新列:

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不同):

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

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

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

删除一列:

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(如果没有指定显示索引,内部字典中的键,被合并并排序来形成结果中的索引):

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:

df_4.T
2013 2014 2015
MD NaN 4.0 4.1
VA 5.1 5.2 NaN

Series的词典创建一个DataFrame

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的索引名称:

df_5.index.name = 'year'
df_5
MD VA
year
2014 NaN 5.2
2015 4.1 NaN

设置DataFrame的列名称:

df_5.columns.name = 'state'
df_5
state MD VA
year
2014 NaN 5.2
2015 4.1 NaN

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

df_5.values

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

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

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。

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

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 以外的值:

df_3.reindex(range(6, 0), fill_value=0)
year state pop unempl

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

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
'''

重索引列:

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

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

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的重索引:

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中删除行:

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中删除列:

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的索引值。

ser_2

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

Series中选择值:

ser_2[0] == ser_2['a']

# True

Series中选择切片:

ser_2[1:4]

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

Series中选择特定值:

ser_2[['b', 'c', 'd']]

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

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

ser_2[ser_2 > 0]

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

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

ser_2['a':'b']

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

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

ser_2['a':'b'] = 0
ser_2

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

Pandas 支持DataFrame中的索引。

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中选择特定列:

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中选择切片:

df_6[:2]
state pop unempl year
0 VA 5.0 NaN 2012
1 VA 5.1 NaN 2013

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

df_6[df_6['pop'] > 5]
state pop unempl year
1 VA 5.1 NaN 2013
2 VA 5.2 6 2014

DataFrame上执行标量比较:

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上执行标量比较,保留满足过滤器的行:

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中选择一行(注意包含终点):

df_6.ix[2:3]
state pop unempl year
2 VA 5.2 6 2014
3 MD 4.0 6 2014

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

df_6.ix[0:2, 'pop']

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

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

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:

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:

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:

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
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
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:

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的索引,并向下广播行:

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的索引,向下广播行并合并不匹配的索引:

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):

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
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 对象:

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 数组上的函数应用于每列:

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 数组上的函数应用于每行:

df_11.apply(func_1, axis=1)

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

应用函数并返回DataFrame:

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

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

df_11['a'].map(func_3)

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

排序和排名

ser_4

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

按照索引排序Series

ser_4.sort_index()

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

按照值排序Series

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

df_12.sort_index()
c a b d
one 4 5 6 7
three 0 1 2 3
two 8 9 10 11

按列倒序排序DaraFrame

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的值:

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,除了通过为每个组分配平均排名来打破关系:

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

ser_11.rank(method='first')

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

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

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可以按行或列排名。

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

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

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 中不一定是唯一的:

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

选择序列的元素:

ser_12['foo']

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

选择DataFrame的元素:

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
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 值。

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
df_6.sum()

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

按行求和:

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:

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
'''

清洗数据(构建中)

  • 替换
  • 删除
  • 连接
from pandas import Series, DataFrame
import pandas as pd

创建DataFrame

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

替换

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

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

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

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的副本:

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

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
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

输入和输出(构建中)

from pandas import Series, DataFrame
import pandas as pd

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

df_1 = pd.read_csv("../data/ozone.csv")

获取DataFrame的摘要:

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的前五行:

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 编码并隐藏索引和标题标签:

df_1.to_csv('../data/ozone_copy.csv', 
            encoding='utf-8', 
            index=False, 
            header=False)

查看数据目录:

!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
'''
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容