python狗狗年龄换算_Python科学计算:pandas

pandas 是 Python 下科学计算非常实用的一个工具。本文将简明扼要地介绍其使用方法。如果想要初步地操作数据,直接阅读本文即可;否则请先学习 numpy 相关的内容。

引言:Series 与 DataFrame

加载 pandas 时,一般也会同时加载 numpy. 默认使用如下的语句:

import numpy as np

import pandas as pd

from pandas import Series, DataFrame

pandas 内置了两种独特的数据结构:Series 与 DataFrame.

系列(Series)

系列是由多个同类型元素组成的有序列向量,有些接近 Python 原生的列表(list)。不同的是,系列包含各元素的一个索引:这个索引可以任意重命名。

s = Series([1, 2, np.nan, 4])

s

0 1.0

1 2.0

2 NaN

3 4.0

dtype: float64

s.index = list('abcd')

s

a 1.0

b 2.0

c NaN

d 4.0

dtype: float64

s["c"]

nan

数据框(DataFrame)

数据框是一个二维的数据结构,特点是:

列内的元素同类型,不同的列之间可以不相同。

索引有两个轴向:axis=0/”index”行,axis=1/”columns” 列。分别用 df.index(行名)与df.columns(列名)调用。

在数据处理中,使用数据框是非常便捷的;而系列我们却很少使用。

数据读写

数据读取

pandas 内置的文件读取函数:

pd.read_csv():参数如下。

names:指定表头(df.columns)。

header:指定整数 n,表示前 n 行会被读作表头。如果 names 指定了,会被设为 0.

engine: “c” 或者 “python”。前者会快一些。

skipinitialspace: 是否忽略紧跟在分隔符后的空格。默认值 False.

na_values:指定一个字符串列表,里面的字符串都会被识别为 NaN。默认的有 [‘’, ‘#N/A’, ‘#N/A N/A’, ‘#NA’, ‘-1.#IND’, ‘-1.#QNAN’, ‘-NaN’, ‘-nan’,‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘nan’.]

na_filter:默认值 True。如果确定文件中不含 NaN,那么指定它为 False 可以提高大文件读取速度。 -skip_blank_lines:是否跳过空白行。默认值 True.

pd.read_table():只要是分隔符文件即可。参数 sep 缺省值是制表符。

pd.read_excel()

以上读取的结果都是 DataFrame. 其他的读取函数不再介绍。

数据写入

df.to_csv()

df.to_excel()

数据创建

以下介绍几种数据框的创建方法。第一种,如果是全数字的数据结构,可以直接从 numpy 中的矩阵创建。

# 参数 index 与 columns 是可选的

arr = np.arange(1, 19).reshape([6, 3])

df = DataFrame(arr, index=list('ABCDEF'), columns=list('ZYX'))

df

ZYX

A

1

2

3

B

4

5

6

C

7

8

9

D

10

11

12

E

13

14

15

F

16

17

18

第二种,通过字典创建。字典的每个键下的值都是格式相同的列表。注意:此时的列会自动根据列名(原字典中的键)从左到右升序排列。

df = DataFrame({"Letters": ["A", "B"], "Age": [12, 34]})

df

AgeLetters

0

12

A

1

34

B

数据框尺寸:df.shape 与 len()

与 numpy 的矩阵类似,数据框拥有属性 shape,返回结果是一个元组:

df = DataFrame(arr, index=list('ABCDEF'), columns=list('ZYX'))

df.shape

(6, 3)

如果使用 Python 原生的 len() 函数,会返回数据框的行数。注意:如果你要基于数据框写循环语句,请利用它们的行名(df.index)而不是利用 len() 函数。这是因为数据框在切片时会保留行名索引;如果简单地使用 for row in range(len(...)) ,会出现 row 与行名不一致的问题。

len(df)

6

预览数据:df.head() / tail() / values

常用的是前两个,用于查看数据框头部 5 行或者尾部 5 行的数据。你也可以传入数字指定查看的行数。

df.head(3)

ZYX

A

1

2

3

B

4

5

6

C

7

8

9

df.tail()

ZYX

B

4

5

6

C

7

8

9

D

10

11

12

E

13

14

15

F

16

17

18

df.values 则是一个有些怪异的命令:它会返回一个 np.array 类型的数据。

df.values

array([[ 1, 2, 3],

[ 4, 5, 6],

[ 7, 8, 9],

[10, 11, 12],

[13, 14, 15],

[16, 17, 18]])

查看 df 的基础信息,使用 df.info() 命令:

df.info()

Index: 6 entries, A to F

Data columns (total 3 columns):

Z 6 non-null int32

Y 6 non-null int32

X 6 non-null int32

dtypes: int32(3)

memory usage: 96.0+ bytes

统计信息:df.describe(), s.value_counts() / unique()

df.describe()

ZYX

count

6.000000

6.000000

6.000000

mean

8.500000

9.500000

10.500000

std

5.612486

5.612486

5.612486

min

1.000000

2.000000

3.000000

25%

4.750000

5.750000

6.750000

50%

8.500000

9.500000

10.500000

75%

12.250000

13.250000

14.250000

max

16.000000

17.000000

18.000000

value_counts() 是一个适用于 Series 的命令。参数 dropna 可以使用。

df.apply(Series.value_counts, dropna=False)

ZYX

1

1.0

NaN

NaN

2

NaN

1.0

NaN

3

NaN

NaN

1.0

4

1.0

NaN

NaN

5

NaN

1.0

NaN

6

NaN

NaN

1.0

7

1.0

NaN

NaN

8

NaN

1.0

NaN

9

NaN

NaN

1.0

10

1.0

NaN

NaN

11

NaN

1.0

NaN

12

NaN

NaN

1.0

13

1.0

NaN

NaN

14

NaN

1.0

NaN

15

NaN

NaN

1.0

16

1.0

NaN

NaN

17

NaN

1.0

NaN

18

NaN

NaN

1.0

unique() 命令有时会配合集合(set)数据结构一同使用:

tmp = Series([1, 2, 3, np.nan, 14, 3, 1])

set_1 = set(tmp.unique())

set_1

{nan,1.0,2.0,3.0,14.0}

更改列类型:pd.to_numeric()

pandas 在读入数据时会自动识别各列的类型。识别的类型可以使用 dtypes 属性:

df.dtypes

Z int32

Y int32

X int32

dtype: object

例如,我们将前两列的属性改为字符串:(这里使用的 applymap 函数会在后面提到)

df[["Z", "Y"]] = df[["Z", "Y"]].applymap(str)

df.dtypes

Z object

Y object

X int32

dtype: object

# Check it

df["Z"][1]

'4'

对于上述的问题,astype() 命令也是一个解决方案:

df[["Z", "Y"]] = df[["Z", "Y"]].astype(str)

如果想转换为数字,pandas 提供了 to_numeric 命令。此命令是作用于 Series 的,因此你可能需要 apply 命令来应用于多个列:

df[["Z", "Y"]] = df[["Z", "Y"]].apply(pd.to_numeric)

df.dtypes

Z int64

Y int64

X int32

dtype: object

注意到该命令有个 errors 参数,用于处理无法正常转换的情况。可以指定以下值:

“ignore”: 如果列中存在无法转换的元素,那么整个列不作转换;

“coerce”:如果列中存在无法转换的元素,仍然转换列,并将这些元素转换为 NaN

tmp = Series([1, 2, "Tree", 4])

pd.to_numeric(tmp, errors="ignore")

0 1

1 2

2 Tree

3 4

dtype: object

pd.to_numeric(tmp, errors="coerce")

0 1.0

1 2.0

2 NaN

3 4.0

dtype: float64

更改行 / 列名:df.rename()

数据框的行名 / 列名列表分别用 df.columns 与 df.index 查看。

df.columns

Index(['Z', 'Y', 'X'], dtype='object')

df.index

Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')

因此,最简单粗暴的行名 / 列名更改方法是:将一个列表赋值过去。

df.columns = list("RQP")

df.head(1)

RQP

A

1

2

3

有时需要只更改几个名称,难道需要创建整个列表吗?这时候使用 df.rename 命令,通过字典的方式替换:

# 在很多函数中,inplace 参数都避免了自赋值的操作

df.rename(columns = {"R": "Z", "Q": "Y", "P": "X"}, inplace=True)

df.head(1)

ZYX

A

1

2

3

数据整理

深度复制:df.copy()

不用多说。如果不进行深度复制,df 与 df2 将会是同址的。

df2 = df.copy()

关于切片时的深度复制问题,会在介绍切片时阐述。

转置:df.T

df.T # 不改变 df

ABCDEF

Z

1

4

7

10

13

16

Y

2

5

8

11

14

17

X

3

6

9

12

15

18

排序

排序分为两种:

按照列名/行名的字母顺序排序列/行,这里称为索引重排;

按照列内/行内的数据间大小关系,排序整个数据框的行/列,这里称为(数据)排序。

索引重排:df.sort_index()

默认参数是 axis=0(重排行),ascending=True(升序)。支持 inplace 参数。

df.sort_index(ascending=False)

ZYX

F

16

17

18

E

13

14

15

D

10

11

12

C

7

8

9

B

4

5

6

A

1

2

3

df.sort_index(axis="columns") # 或 axis = 1

XYZ

A

3

2

1

B

6

5

4

C

9

8

7

D

12

11

10

E

15

14

13

F

18

17

16

数据排序:df.sort_values()

此时只能根据列来排序。参数 na_position 默认值是 “last”,也可以指定 “first”.

df.sort_values(by="Z", ascending=False)

ZYX

F

16

17

18

E

13

14

15

D

10

11

12

C

7

8

9

B

4

5

6

A

1

2

3

切片与选取

普通选取

选取单列:df['X'] 或者 df.X

选取多列:df[['X', 'Y']]

选取行:例如前两行 df[:2]

按照标签:df.loc['A'] / df.loc[['A', 'E'], 'X']

按照索引序号:第三行 df.iloc[2];df.iloc[:2, :1]

单元素选取:df.at / df.iat,只能选取单个元素。

在多数情况下,请尽量使用 loc/iloc 命令。它们是深度复制命令,这样可以避免多数的引用问题。

布尔型选取

df[(df.X > 10) & (df.Y < 15)]

ZYX

D

10

11

12

E

13

14

15

df[df > 10] # 对整个 df 进行判断,不符合的填充 NaN

ZYX

A

NaN

NaN

NaN

B

NaN

NaN

NaN

C

NaN

NaN

NaN

D

NaN

11.0

12.0

E

13.0

14.0

15.0

F

16.0

17.0

18.0

df[df.X.isin([3, 6, 8])] # 根据列 X 中是否有列表里对应元素,筛选行

ZYX

A

1

2

3

B

4

5

6

缺失数据:df.dropna() / fillna()

df.dropna() 将筛选含有 NaN 的行/列(用参数 axis 指定),支持 inplace 参数。参数 how 指定筛选的方式:

df.dropna(how=”any”):行/列中存在 NaN 就抛弃。

df.dropna(how=”all”):只有当行/列全为 NaN 时才抛弃。

参数 thresh 指定了行/列中最低应存在的非 NaN 元素个数;如果非 NaN 元素个数小于这一阈值,该行/列会被抛弃。

df.fillna() 将 NaN 替换为另外的数值,用参数 value 指定。例如:df.fillna(value=-1)。

pd.isnull() 命令将会返回一个布尔型数据框,检验各元素是否为 NaN。

pd.isnull(df).head(2)

ZYX

A

False

False

False

B

False

False

False

查找替换:df.replace()

df.replace([1, 2], [100, 200])

ZYX

A

100

200

3

B

4

5

6

C

7

8

9

D

10

11

12

E

13

14

15

F

16

17

18

合并与分组

合并:df.append() / join(), pd.concat()

append() 是源自 list 类型的函数,类似 list 类型的 DataFrame 也可以调用。其作用是行合并。

df1 = df

df2 = df.rename(columns={"X": "Z", "Z": "P"})

df1.append(df2)

PXYZ

A

NaN

3.0

2

1

B

NaN

6.0

5

4

C

NaN

9.0

8

7

D

NaN

12.0

11

10

E

NaN

15.0

14

13

F

NaN

18.0

17

16

A

1.0

NaN

2

3

B

4.0

NaN

5

6

C

7.0

NaN

8

9

D

10.0

NaN

11

12

E

13.0

NaN

14

15

F

16.0

NaN

17

18

pd.concat() 则是一个可以指定合并轴的函数:

pd.concat([df1, df2], axis="columns") # 列合并

ZYXPYZ

A

1

2

3

1

2

3

B

4

5

6

4

5

6

C

7

8

9

7

8

9

D

10

11

12

10

11

12

E

13

14

15

13

14

15

F

16

17

18

16

17

18

如果按默认的合并方式 join=”outer”,那么 concat(axis="index") 的结果与 append() 一致。但你可以指定内联合并:

pd.concat([df1, df2], axis="index", join="inner")

YZ

A

2

1

B

5

4

C

8

7

D

11

10

E

14

13

F

17

16

A

2

3

B

5

6

C

8

9

D

11

12

E

14

15

F

17

18

df.join() 则允许你使用类似 SQL 的方法进行合并。利用其参数 how 与 on 等可以控制合并方式。

分组:df.groupby()

df.groupby() 函数与 R 语言中的 aggregate() 有异曲同工之妙。

dt = DataFrame({"A": [1, 2, 3, 4, 5, 6],

"B": ["a", "a", "a", "b", "b", "b"],

"C": ["x", "x", "y", "y", "z", "z"],

"D": [1, 1, 1, 2, 2, 2]})

dt.groupby("B")

返回值无法直接理解,需要配合统计函数使用。可以参考本文“统计函数”一节的内容。

dt.groupby("B").mean() # 列 C 无法计算 mean(),被忽略

AD

B

a

2

1

b

5

2

也可以同时应用到多个列。如果你了解过 R 语言中“因子”的概念,会对该函数的理解有所帮助。列 B 有两个水平,列 C 有三个。

dt.groupby(["B", "C"]).mean()

AD

BC

ax

1.5

1.0

y

3.0

1.0

by

4.0

2.0

z

5.5

2.0

groupby() 函数默认会将函数应用到所有其他的列。如果你只想计算指定的列,那么:

dt.groupby(["B", "C"])["A"].mean()

B C

a x 1.5

y 3.0

b y 4.0

z 5.5

Name: A, dtype: float64

函数式应用:df.apply()/applymap()

df.apply() 函数在前面已经介绍过。参数主要是 axis,以及也能继承要应用的函数的参数。所有可以应用于 Series 的函数都能够这样应用到不同的列上。这里再次使用上文使用过的 Series.value_counts() 函数。

df.apply(Series.value_counts, dropna=False).head(4)

ZYX

1

1.0

NaN

NaN

2

NaN

1.0

NaN

3

NaN

NaN

1.0

4

1.0

NaN

NaN

一个用 df.applymap() 实现的小数位数处理,保留到第二位:

df.applymap(lambda x: "%.2f" % x)

ZYX

A

1.00

2.00

3.00

B

4.00

5.00

6.00

C

7.00

8.00

9.00

D

10.00

11.00

12.00

E

13.00

14.00

15.00

F

16.00

17.00

18.00

统计函数

除了上文介绍过的 df.describe(),以下运算均以“列”为基本单位:

df.mean()

df.corr()

df.count():非 NaN 数据计数

df.max()/df.minx()

df.median()

df.std()

其他

如果你有更多的疑问,请参阅 numpy 一文。

原文链接:https://wklchris.github.io/Py3-pandas.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
D:\python\python3.9.5\python.exe C:/Users/马斌/Desktop/NGSIM_data_processing/80s/x-y.py Traceback (most recent call last): File "C:\Users\马斌\Desktop\NGSIM_data_processing\80s\x-y.py", line 6, in <module> data = pd.read_csv('车辆:1499序:2结果数据换算单位.csv') File "D:\python\python3.9.5\lib\site-packages\pandas\io\parsers\readers.py", line 912, in read_csv return _read(filepath_or_buffer, kwds) File "D:\python\python3.9.5\lib\site-packages\pandas\io\parsers\readers.py", line 577, in _read parser = TextFileReader(filepath_or_buffer, **kwds) File "D:\python\python3.9.5\lib\site-packages\pandas\io\parsers\readers.py", line 1407, in __init__ self._engine = self._make_engine(f, self.engine) File "D:\python\python3.9.5\lib\site-packages\pandas\io\parsers\readers.py", line 1679, in _make_engine return mapping[engine](f, **self.options) File "D:\python\python3.9.5\lib\site-packages\pandas\io\parsers\c_parser_wrapper.py", line 93, in __init__ self._reader = parsers.TextReader(src, **kwds) File "pandas\_libs\parsers.pyx", line 548, in pandas._libs.parsers.TextReader.__cinit__ File "pandas\_libs\parsers.pyx", line 637, in pandas._libs.parsers.TextReader._get_header File "pandas\_libs\parsers.pyx", line 848, in pandas._libs.parsers.TextReader._tokenize_rows File "pandas\_libs\parsers.pyx", line 859, in pandas._libs.parsers.TextReader._check_tokenize_status File "pandas\_libs\parsers.pyx", line 2017, in pandas._libs.parsers.raise_parser_error UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid start byte Process finished with exit code 1
最新发布
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值