Python 数据处理库 pandas

核心数据结构

pandas最核心的就是SeriesDataFrame两个数据结构。

名称维度说明
Series 1维 带有标签的同构类型数组
DataFrame 2维 表格结构,带有标签,大小可变,且可以包含异构的数据列

DataFrame可以看做是Series的容器,即:一个DataFrame中可以包含若干个Series。

series

由于Series是一堆结构的数据,我们可以直接通过数组来创建这种数据,像这样:

import pandas as pd
import numpy as np
 
series1 = pd.Series([1, 2, 3, 4])
print("series1:\n{}\n".format(series1))

# series1:
# 0    1
# 1    2
# 2    3
# 3    4
# dtype: int64
  • 输出的最后一行是Series中数据的类型,这里的数据都是int64类型的。
  • 数据在第二列输出,第一列是数据的索引

我们分别打印出Series中的数据和索引

print("series1.values: {}\n".format(series1.values))
 
print("series1.index: {}\n".format(series1.index))

# series1.values: [1 2 3 4]
# series1.index: RangeIndex(start=0, stop=4, step=1)

我们可以指定索引的类型,例如字符串

series2 = pd.Series([1, 2, 3, 4, 5, 6, 7],
index=["C", "D", "E", "F", "G", "A", "B"])
print("series2:\n{}\n".format(series2))
print("E is {}\n".format(series2["E"]))

# series2:
# C    1
# D    2
# E    3
# F    4
# G    5
# A    6
# B    7
# dtype: int64

# E is 3

DataFrame

通过Numpy接口来创建一个4x4的矩阵,以此来创建DataFrame

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df1 = pd.DataFrame(np.arange(16).reshape(4,4))
 5 print("df1:\n{}\n".format(df1))
 6 
 7 # df1:
 8 #     0   1   2   3
 9 # 0   0   1   2   3
10 # 1   4   5   6   7
11 # 2   8   9  10  11
12 # 3  12  13  14  15
View Code

默认的索引和列名都是[0,N-1]的形式,同样我们可以指定列名和索引,

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df2 = pd.DataFrame(np.arange(16).reshape(4,4),
 5 columns=["column1", "column2", "column3", "column4"],
 6 index=["a", "b", "c", "d"])
 7 print("df2:\n{}\n".format(df2))
 8 
 9 # df2:
10 #    column1  column2  column3  column4
11 # a        0        1        2        3
12 # b        4        5        6        7
13 # c        8        9       10       11
14 # d       12       13       14       15
View Code

我们也可以指定结构来创建DataFrame

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df3 = pd.DataFrame({"note" : ["C", "D", "E", "F", "G", "A", "B"],
 5     "weekday": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]})
 6 print("df3:\n{}\n".format(df3))
 7 
 8 # df3:
 9 #   note weekday
10 # 0    C     Mon
11 # 1    D     Tue
12 # 2    E     Wed
13 # 3    F     Thu
14 # 4    G     Fri
15 # 5    A     Sat
16 # 6    B     Sun
View Code

注意:

  • DataFrame的不同列可以是不同的数据类型

  • 如果以Series数组来创建DataFrame,每个Series将成为一行,而不是一列

 1 import pandas as pd
 2 import numpy as np
 3  
 4 noteSeries = pd.Series(["C", "D", "E", "F", "G", "A", "B"],
 5     index=[1, 2, 3, 4, 5, 6, 7])
 6 weekdaySeries = pd.Series(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
 7     index=[1, 2, 3, 4, 5, 6, 7])
 8 df4 = pd.DataFrame([noteSeries, weekdaySeries])
 9 print("df4:\n{}\n".format(df4))
10 
11 # df4:
12 #      1    2    3    4    5    6    7
13 # 0    C    D    E    F    G    A    B
14 # 1  Mon  Tue  Wed  Thu  Fri  Sat  Sun
View Code

我们还可以“添加”或“删除”列数据

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df3 = pd.DataFrame({"note" : ["C", "D", "E", "F", "G", "A", "B"],
 5                     "weekday": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]})
 6 df3["No."] = pd.Series([1, 2, 3, 4, 5, 6, 7])
 7 print("df3:\n{}\n".format(df3))
 8  
 9 del df3["weekday"]
10 print("df3:\n{}\n".format(df3))
11 
12 # df3:
13 #   note weekday  No.
14 # 0    C     Mon    1
15 # 1    D     Tue    2
16 # 2    E     Wed    3
17 # 3    F     Thu    4
18 # 4    G     Fri    5
19 # 5    A     Sat    6
20 # 6    B     Sun    7
21 
22 # df3:
23 #   note  No.
24 # 0    C    1
25 # 1    D    2
26 # 2    E    3
27 # 3    F    4
28 # 4    G    5
29 # 5    A    6
30 # 6    B    7
View Code

index对象与数据访问

同样可以通过索引来获取DataFrame的行和列

1 print("df3.columns\n{}\n".format(df3.columns))
2 print("df3.index\n{}\n".format(df3.index))
3 
4 # df3.columns
5 # Index(['note', 'No.'], dtype='object')
6 
7 # df3.index
8 # RangeIndex(start=0, stop=7, step=1)
View Code

注意:

  • Index并非集合,因此其中可以包含重复的数据

  • Index对象的值是不可以改变,因此可以通过它安全的访问数据

DataFrane提供了下面两个操作符来访问其中的数据

  • loc:通过行和列的索引来访问数据

  • iloc:通过行和列的下标来访问数据

 1 print("Note C, D is:\n{}\n".format(df3.loc[[0, 1], "note"]))
 2 print("Note C, D is:\n{}\n".format(df3.iloc[[0, 1], 0]))
 3 
 4 # Note C, D is:
 5 # 0    C
 6 # 1    D
 7 # Name: note, dtype: object
 8 
 9 # Note C, D is:
10 # 0    C
11 # 1    D
12 # Name: note, dtype: object
View Code

第一行代码访问了行索引为0和1,列索引为“note”的元素,第二行代码访问了行下标为0和1对于df3来说,行索引和行下标刚好是一样的,所以这里都是0和1,但它们却是不同的含义),列下标为0的元素。

文件操作

读取Excel文件

注:要读取Excel文件,还需要安装另外一个库;xlrd

pip install xlrd

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df1 = pd.read_excel("data/test.xlsx")
 5 print("df1:\n{}\n".format(df1))
 6 
 7 # df1:
 8 #    C  Mon
 9 # 0  D  Tue
10 # 1  E  Wed
11 # 2  F  Thu
12 # 3  G  Fri
13 # 4  A  Sat
14 # 5  B  Sun
View Code

 读取csv文件

1 C,Mon
2 D,Tue
3 E,Wed
4 F,Thu
5 G,Fri
6 A,Sat
第一个CSV文件内容
1 C|Mon
2 D|Tue
3 E|Wed
4 F|Thu
5 G|Fri
6 A|Sat
第二个CSV文件的内容

读取CSV文件

1 import pandas as pd
2 import numpy as np
3 df2 = pd.read_csv("data/test1.csv")
4 print("df2:\n{}\n".format(df2))
5 # df3 = pd.read_csv("data/test2.csv", sep="|")
6 # print("df3:\n{}\n".format(df3))
View Code

我们可以发现,第二个CSV文件并不是通过逗号分隔的,我们通常指定分隔符的方式来读取这个文件。

read_csv支持非常多的参数用来调整读取的参数

参数说明
path 文件路径
sep或者delimiter 字段分隔符
header 列名的行数,默认是0(第一行)
index_col 列号或名称用作结果中的行索引
names 结果的列名称列表
skiprows 从起始位置跳过的行数
na_values 代替NA的值序列
comment 以行结尾分隔注释的字符
parse_dates 尝试将数据解析为datetime。默认为False
keep_date_col 如果将列连接到解析日期,保留连接的列。默认为False
converters 列的转换器
dayfirst 当解析可以造成歧义的日期时,以内部形式存储。默认为False
data_parser 用来解析日期的函数
nrows 从文件开始读取的行数
iterator 返回一个TextParser对象,用于读取部分内容
chunksize 指定读取块的大小
skip_footer 文件末尾需要忽略的行数
verbose 输出各种解析输出的信息
encoding 文件编码
squeeze 如果解析的数据只包含一列,则返回一个Series
thousands 千数量的分隔符

详细的read_csv函数说明请参见这里:pandas.read_csv

处理无效值

主要有两种处理方法:直接忽略这些无效值;或者将无效值替换成有效值。

我们先创建一个包含无效值的数据结构。然后通过pandas.isna函数来确认哪些值是无效的:

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df = pd.DataFrame([[1.0, np.nan, 3.0, 4.0],
 5                   [5.0, np.nan, np.nan, 8.0],
 6                   [9.0, np.nan, np.nan, 12.0],
 7                   [13.0, np.nan, 15.0, 16.0]])
 8  
 9 print("df:\n{}\n".format(df));
10 print("df:\n{}\n".format(pd.isna(df)))
11 
12 # df:
13 #       0   1     2     3
14 # 0   1.0 NaN   3.0   4.0
15 # 1   5.0 NaN   NaN   8.0
16 # 2   9.0 NaN   NaN  12.0
17 # 3  13.0 NaN  15.0  16.0
18  
19 # df:
20 #        0     1      2      3
21 # 0  False  True  False  False
22 # 1  False  True   True  False
23 # 2  False  True   True  False
24 # 3  False  True  False  False
View Code

忽略无效值

我们可以通过pandas.DataFrame.dropna函数抛弃无效值

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df = pd.DataFrame([[1.0, np.nan, 3.0, 4.0],
 5                   [5.0, np.nan, np.nan, 8.0],
 6                   [9.0, np.nan, np.nan, 12.0],
 7                   [13.0, np.nan, 15.0, 16.0]])
 8  
 9 print("df.dropna():\n{}\n".format(df.dropna()));
10 
11 # df.dropna():
12 # Empty DataFrame
13 # Columns: [0, 1, 2, 3]
14 # Index: []
View Code

对于原先的结构,当无效值全部被抛弃之后,将不再是一个有效的DataFrame,所以才会是以上结果

我们也可以选择抛弃整列都是无效值的那一列:

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df = pd.DataFrame([[1.0, np.nan, 3.0, 4.0],
 5                   [5.0, np.nan, np.nan, 8.0],
 6                   [9.0, np.nan, np.nan, 12.0],
 7                   [13.0, np.nan, 15.0, 16.0]])
 8  
 9 print("df.dropna(axis=1,how='all'):\n{}\n".format(df.dropna(axis=1, how='all')));
10 
11 # df.dropna(axis=1, how='all'):
12 #       0     2     3
13 # 0   1.0   3.0   4.0
14 # 1   5.0   NaN   8.0
15 # 2   9.0   NaN  12.0
16 # 3  13.0  15.0  16.0
View Code

注:axis=1表示列的轴。how可以取值’any’或者’all’,默认是前者。

替换无效值

我们也可以通过fillna函数将无效值替换成为有效值

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df = pd.DataFrame([[1.0, np.nan, 3.0, 4.0],
 5                   [5.0, np.nan, np.nan, 8.0],
 6                   [9.0, np.nan, np.nan, 12.0],
 7                   [13.0, np.nan, 15.0, 16.0]])
 8  
 9 print("df:\n{}\n".format(df));
10 
11 print("df.fillna(1):\n{}\n".format(df.fillna(1)));
12 
13 # df:
14 #       0   1     2     3
15 # 0   1.0 NaN   3.0   4.0
16 # 1   5.0 NaN   NaN   8.0
17 # 2   9.0 NaN   NaN  12.0
18 # 3  13.0 NaN  15.0  16.0
19 
20 # df.fillna(1):
21 #       0    1     2     3
22 # 0   1.0  1.0   3.0   4.0
23 # 1   5.0  1.0   1.0   8.0
24 # 2   9.0  1.0   1.0  12.0
25 # 3  13.0  1.0  15.0  16.0
View Code

将无效值全部替换成同样的数据可能意义不大,因此我们可以指定不同的数据来进行填充。为了便于操作,在填充之前,我们可以先通过rename方法修改行和列的名称:

 1 import pandas as pd
 2 import numpy as np
 3  
 4 df = pd.DataFrame([[1.0, np.nan, 3.0, 4.0],
 5                   [5.0, np.nan, np.nan, 8.0],
 6                   [9.0, np.nan, np.nan, 12.0],
 7                   [13.0, np.nan, 15.0, 16.0]])
 8  
 9 print("df:\n{}\n".format(df));
10 print("df:\n{}\n".format(pd.isna(df)))
11 
12 df.rename(index={0: 'index1', 1: 'index2', 2: 'index3', 3: 'index4'},
13           columns={0: 'col1', 1: 'col2', 2: 'col3', 3: 'col4'},
14           inplace=True);
15 df.fillna(value={'col2': 2}, inplace=True)  # 把第2列的空值变成2
16 df.fillna(value={'col3': 7}, inplace=True)  # 把第3列的空值变成7
17 print("df:\n{}\n".format(df));
18 
19 # df:
20 #       0   1     2     3
21 # 0   1.0 NaN   3.0   4.0
22 # 1   5.0 NaN   NaN   8.0
23 # 2   9.0 NaN   NaN  12.0
24 # 3  13.0 NaN  15.0  16.0
25 
26 # df:
27 #        0     1      2      3
28 # 0  False  True  False  False
29 # 1  False  True   True  False
30 # 2  False  True   True  False
31 # 3  False  True  False  False
32 
33 # df:
34 #         col1  col2  col3  col4
35 # index1   1.0   2.0   3.0   4.0
36 # index2   5.0   2.0   7.0   8.0
37 # index3   9.0   2.0   7.0  12.0
38 # index4  13.0   2.0  15.0  16.0
View Code

处理字符串

Seriesstr字段包含了一系列的函数用来处理字符串。并且,这些函数会自动处理无效值。

 1 import pandas as pd
 2  
 3 s1 = pd.Series([' 1', '2 ', ' 3 ', '4', '5']);
 4 print("s1.str.rstrip():\n{}\n".format(s1.str.lstrip()))
 5 print("s1.str.strip():\n{}\n".format(s1.str.strip()))
 6 print("s1.str.isdigit():\n{}\n".format(s1.str.isdigit()))
 7 
 8 # s1.str.rstrip():
 9 # 0     1
10 # 1    2 
11 # 2    3 
12 # 3     4
13 # 4     5
14 # dtype: object
15 
16 # s1.str.strip():
17 # 0    1
18 # 1    2
19 # 2    3
20 # 3    4
21 # 4    5
22 # dtype: object
23 
24 # s1.str.isdigit():
25 # 0    False
26 # 1    False
27 # 2    False
28 # 3     True
29 # 4     True
30 # dtype: bool
View Code

我们还能对字符串进行大写、小写、以及字符串长度的处理。

 1 import pandas as pd
 2  
 3 s2 = pd.Series(['Stairway to Heaven', 'Eruption', 'Freebird',
 4                     'Comfortably Numb', 'All Along the Watchtower'])
 5 print("s2.str.lower():\n{}\n".format(s2.str.lower()))
 6 print("s2.str.upper():\n{}\n".format(s2.str.upper()))
 7 print("s2.str.len():\n{}\n".format(s2.str.len()))
 8 
 9 # s2.str.lower():
10 # 0          stairway to heaven
11 # 1                    eruption
12 # 2                    freebird
13 # 3            comfortably numb
14 # 4    all along the watchtower
15 # dtype: object
16 
17 # s2.str.upper():
18 # 0          STAIRWAY TO HEAVEN
19 # 1                    ERUPTION
20 # 2                    FREEBIRD
21 # 3            COMFORTABLY NUMB
22 # 4    ALL ALONG THE WATCHTOWER
23 # dtype: object
24 
25 # s2.str.len():
26 # 0    18
27 # 1     8
28 # 2     8
29 # 3    16
30 # 4    24
31 # dtype: int64
View Code

参考文献

https://paul.pub/pandas-tutorial/

posted @ 2018-09-24 17:59  凌逆战  阅读(466)  评论(0编辑  收藏  举报