Python module1(os pandas)

列举Python中常用的模块和包(一)。os 模块 和 pandas包。

os模块

相关函数

增删改查

os.listdir() 返回指定目录下的所有文件和目录名
os.mkdir()
os.rmdir() 删除空目录
os.chdir() 改变当前目录,到指定目录中
os.rename() 重命名目录名或者文件名

判断

os.path.exists()
os.path.isfile()
os.path.isdir()
os.path.join(path,name)

输入一个文件的路径
os.path.basename() 返回输入的文件名部分
os.path.dirname() 返回输入的路径部分
os.path.abspath() 获得绝对路径

操作举例

创建/删除目录

1
2
3
4
5
6
7
8
9
10
import os
new_dir=""

if not os.path.exists(new_dir):
os.makedirs(new_dir)

old_dir=""
if os.path.exists(old_dir):
if len(os.path.listdir) == 0:
os.rmdir(old_dir)

访问目录下的文件

1
2
3
4
5
6
7
8
9
import os
# 查找文件名包含指定字符串的文件
sub_str="xxx"
cur_dir=os.getcwd()
files=os.listdir(cur_dir)
for item in files:
if os.path.isfile(os.path.join(cur_dir,item)):
if item.find(sub_str) != -1:
print(os.path.join(cur_dir,item))

pandas包

pandas官方API文档

Series结构

参考

Series对象本质上是一个NumPy的数组,因此NumPy的数组处理函数可以直接对Series进行处理。但是Series除了可以使用位置作为下标存取元素之外,还可以使用标签下标存取元素,这一点和字典相似。每个Series对象实际上都由两个数组组成:

index: 它是从NumPy数组继承的Index对象,保存标签信息,索引值必须是唯一的和散列的,默认从0开始
values: 保存值的NumPy数组。

创建

下面介绍Series的创建方式, 和 Series的几个属性,array, values, dtype, shape,size等

使用列表创建

1
2
3
4
5
6
7
8
9
10
data = ['a','b','c','d','e']
res= pd.Series(data,index=[i for i in range(1,6)],dtype=str)
print(res)

1 a
2 b
3 c
4 d
5 e
dtype: object

使用字典创建

使用字典创建的话,字典的键用于构建索引,值作为values

1
2
3
4
5
6
7
8
data = {"a":[1,2,3],"b":2,"c":3,"d":4}
res = pd.Series(data)
print('{}\n'.format(res))
print('array属性:{}\n'.format(res.array))
print('values属性:{}\n'.format(res.values))
print('dtype属性:{}\n'.format(res.dtype))
print('shape属性:{}\n'.format(res.shape))
print('size属性:{}\n'.format(res.size))

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a    [1, 2, 3]
b 2
c 3
d 4
dtype: object

array属性:<PandasArray>
[[1, 2, 3], 2, 3, 4]
Length: 4, dtype: object

values属性:[list([1, 2, 3]) 2 3 4]

dtype属性:object

shape属性:(4,)

size属性:4

常量创建

1
2
3
4
5
6
7
8
9
10
# 如果数据是常量值,则必须提供索引。将重复该值以匹配索引的长度。
res = pd.Series(5,index=[1,2,3,4,5])
print(res)

1 5
2 5
3 5
4 5
5 5
dtype: int64

增删改查

1、查询

Series是类似字典key:value形式的索引,不支持负数索引。

访问主要包括标签索引loc和位置索引iloc。当然也包括切片(位置切片和标签切片)进行访问。访问的时候,如果不注明loc和iloc会自动进行判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
data = [1,2,3,4,5]
res = pd.Series(data,index=["a","b","c","d","e"])

# 切片方式
print(res[0:3], '\n') # 这里跟python的切片一样
print(res['a':'d'], '\n')

a 1
b 2
c 3
dtype: int64

a 1
b 2
c 3
d 4
dtype: int64

# 索引方式
print(res[3], '\n') # 或者 print(res.iloc[3], '\n')
print(res['a'], '\n') # 或者 print(res.loc['a'], '\n')

4

1

# 检索多个值 标签用中括号包裹
print(res[["a","b"]], '\n') # 如果用没有的标签检索则会抛出异常KeyError: 'f'
print(res[[2,4]])

a 1
b 2
dtype: int64

c 3
e 5
dtype: int64

# 布尔数组方式

print(res > 5)
print(res[res>5]) # 相当于传入一个布尔数组

a False
b False
c False
d True
e True
dtype: bool
d 4
e 5
dtype: int64

使用head()/tail()查看前几个和后几个

1
2
3

res.head(3) # 查看前三个
res.tail(2) # 查看后两个

2、增改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

x = pd.Series([10,23,31,16],index=list("abcd"))

# 可以将索引看成字典中的键,当键(索引)不存在的时候,相当于增加值
x['e'] = 10000

# 修改值的时候,可以直接访问修改,也可以用 loc。

x['a'] = 6
x.loc['c'] = 22

print(x)

a 6
b 23
c 22
d 16
e 10000
dtype: int64

还有一种方式是Series之间的append。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
s1 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","e"])
s2 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","f"])
s = s1.append(s2)
print(s)

a 1
b 2
c 3
d 4
e 5
a 1
b 2
c 3
d 4
f 5
dtype: int64

3、删除

del 就地删除

1
2
3
4
5
6
7
8
9
del x["b"]

print(x)

a 10
c 31
d 16
e 10000
dtype: int64

drop 返回一个新的Series, 原Series不受影响。当指定了inplace=True后,才属于就地删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
y = x.drop("a")

print(y)
print(x)

c 31
d 16
e 10000
dtype: int64
a 10
c 31
d 16
e 10000
dtype: int64

# 使用drop一次性删除多个值:提供一个标签数组
# x.drop(["a","c"],inplace=True)

其他操作

元素去重

1
2
3
4
s = pd.Series(data=[1,1,2,2,3,4,5,6,6,6,7,6,6,7,8])
s.unique()

array([1, 2, 3, 4, 5, 6, 7, 8])

其实所谓添加就是合并两个Series。

监测缺失

1
2
isnull()  # 缺失的数据返回的布尔值为True
notnull() # 缺失的数据返回的布尔值为False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
s1 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","e"])
s2 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","f"])
s = s1 + s2
s.isnull() # 缺失的数据返回的布尔值为True

a False
b False
c False
d False
e True
f True
dtype: bool

# 根据这个和之前提到的布尔数组访问, 取出所有为空或者不为空的数据可以这么办
s[s.isnull()] # 取所有空值

e NaN
f NaN
dtype: float64

s[s.notnull()] # 取出不为空的数据

a 2.0
b 4.0
c 6.0
d 8.0
dtype: float64

Series之间的运算

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
# 当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
s1 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","e"])
s2 = pd.Series(data=[1,2,3,4,5],index=["a","b","c","d","f"])
s = s1 + s2
s

a 2.0
b 4.0
c 6.0
d 8.0
e NaN
f NaN
dtype: float64

DataFrame结构

DataFrame的API

参考

创建

pandas的DataFrame方法需要传入一个可迭代的对象(列表,元组,字典等), 所以要么是一个dict下每个key下面有个list存,一个list存一列的数据,要么一个list下面存多个dict,每个dict代表一行。

1、使用dict进行创建

1
2
3
4
5
6
7
test_dict = {'id':[1,2,3,4,5,6],'name':['Alice','Bob','Cindy','Eric','Helen','Grace '],'math':[90,89,99,78,97,93],'english':[89,94,80,94,94,90]}

test_dict_df = pd.DataFrame(data=test_dict)

//或者直接

test_dict_df = pd.DataFrame(test_dict)

生成结果:

1
2
3
4
5
6
7
   id    name  math  english
0 1 Alice 90 89
1 2 Bob 89 94
2 3 Cindy 99 80
3 4 Eric 78 94
4 5 Helen 97 94
5 6 Grace 93 90

2、使用list创建

1
2
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)

结果

1
2
3
4
	c1	 c2
0 10 100
1 11 110
2 12 120

看个特别的例子:如果想要生成只有一行的DataFrame

如果写成test_dict_df = pd.DataFrame({'id':1,'name':'Alice'})

会报错If using all scalar values, you must pass an index 如果都是标量,需要加入index

1
2
3
4
5
6
7
#按照提示进行修改
test_dict_df1 = pd.DataFrame({'id':1,'name':'Alice'}, index = [0])

#或者转化成之前介绍的两种形式进行创建

test_dict_df2 = pd.DataFrame([{'id':1,'name':'Alice'}])
test_dict_df3 = pd.DataFrame({'id':[1],'name':['Alice']})

2、选择部分列

有些时候我们只需要选择dict中部分的键当做DataFrame的列,那么我们可以使用columns参数,例如我们只选择’id’,’name’列:

test_dict_df = pd.DataFrame(data=test_dict,columns=['id','name'])

4、read_table 函数构建

read_table文档定义

df = pd.read_table(file_path, header = None, sep = '::', names=['userID', 'movieID', 'rate', 'timestamp'])

几个重要参数:

  • filepath_path:

可以输入所有的string path,包括URL,诸如http, ftp, s3, gs, and file。

例如:file://localhost/path/to/table.csv

  • sep:

分隔符,如果不注明的话自动检测,同时支持正则表达式的写法。如s+

  • header:

计算开多少行用于列名。大概方式就是如果这个参数为0,表明我输入的这个文件的第一行是列名,如果该参数为None,说明文件第一行没有列名,我在names参数里面说清楚列名。如果names参数里面显式地规定,header参数默认为None。如果names参数没有输入,header参数默认为0,会去文件第一行找列名。

  • names:

列名序列,列名的重复不被允许。

3、使用csv文件构建DataFrame

df = pd.read_csv('./xxx.csv')

主要参数和read_table差不多
函数参数参考

把DataFrame存入csv文件

1
2
csv_file = open('Coke_beautiful.csv', 'w')
df.to_csv(csv_file)

访问

逐行遍历

iterrows(): 将DataFrame迭代为(index, Series)对。
itertuples(): 将DataFrame迭代为元组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for index, content in test_dict_df.iterrows():
if index == 0:
print(content)
print(content[0])
print(content['math'])

输出:
id 1
name Alice
math 90
english 89
Name: 0, dtype: object
1
90

# itertuplrs() 返回的元组第一个数值是index,后续是每一行数值
for content in test_dict_df.itertuples():
if getattr(content, 'Index') == 0:
print(content[0],'-->',content[1:])
输出:
0 --> (1, 'Alice', 90, 89)

按列遍历

df.items, Iterate over (column name, Series) pairs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
for label, content in test_dict_df.items():
print(label)
print(content)

输出:
id
0 1
1 2
2 3
3 4
4 5
5 6
6 7
Name: id, dtype: int64
name
0 Alice
1 Bob
2 Cindy
3 Eric
4 Helen
5 Grace
6 Iric
Name: name, dtype: object
math
0 90
1 89
2 99
3 78
4 97
5 93
6 92
Name: math, dtype: int64
english
0 89
1 94
2 80
3 94
4 94
5 90
6 90
Name: english, dtype: int64

添加

1、添加列(insert)

1
2
3
new_columns = [92,94,89,77,87,91]
test_dict_df.insert(2,'pyhsics',new_columns)
#test_dict_df.insert(2,'pyhsics',new_columns,allow_duplicates=True)

结果:

1
2
3
4
5
6
7
   id    name  pyhsics  math  english
0 1 Alice 92 90 89
1 2 Bob 94 89 94
2 3 Cindy 89 99 80
3 4 Eric 77 78 94
4 5 Helen 87 97 94
5 6 Grace 91 93 90

DataFrame默认不允许添加重复的列,但是在insert函数中有参数allow_duplicates=True,设置为True后,就可以添加重复的列

2、添加行(loc)

loc实际是定位的操作,如果loc[index]中的index已经存在,则新的值会覆盖之前的值。也可以作为修改和添加使用。

1
2
new_line = [7,'Iric',99, 91]
test_dict_df.loc[6]= new_line

3.使用append

1
test_dict_df = test_dict_df.append(pd.DataFrame({'id':[8],'name':['Alice']}), ignore_index = True)

append之后生成一个新的DataFrame再赋给原先的,就相当于添加了一行。如果不赋给test_dict_df,这个DataFrame不会改变。

当然append用于Dataframe之间的合并,可以直接添加多行。没有填充的数值会用NaN显示。如果想要添加的index不出现重复的情况,可以通过设置ignore_index=True来避免。

1
2
3
4
5
6
7
8
9
  id	name	math	english
0 1 Alice 90.0 89.0
1 2 Bob 89.0 94.0
2 3 Cindy 99.0 80.0
3 4 Eric 78.0 94.0
4 5 Helen 97.0 94.0
5 6 Grace 93.0 90.0
6 7 Iric 92.0 90.0
7 8 Alice NaN NaN

append()除了直接拼接 DataFrame,dict和Series也可以。

1
2
3
4
a = {"id":1,"name":'Breeze'}
test_dict_df = test_dict_df.append(a,ignore_index=True)
series = pd.Series({"id":3,"math":2})
test_dict_df = test_dict_df.append(series, ignore_index=True)

筛选

loc方法

Access a group of rows and columns by label(s) or a boolean array.

一般用loc,根据给定的索引进行定位(只能先访问index,再访问列)。支持切片,或者条件选择构建一个布尔数组。

1
2
3
4
5
6
test_dict = {'id':[1,2,3,4,5,6],'name':['Alice','Bob','Cindy','Eric','Helen','Grace '],'math':[90,89,99,78,97,93],'english':[89,94,80,94,94,90]}
data = pd.DataFrame(test_dict)
data.loc[6] = [7,'Iricss',99, 91]
data.loc[7] = [7,'Iric',99, 91]
print(data.loc[1:4, 'id':'math'])
print(data.loc[data['english'] > 90])

输出

1
2
3
4
5
6
7
8
9
10
11
   id   name  math
1 2 Bob 89
2 3 Cindy 99
3 4 Eric 78
4 5 Helen 97
id name math english
1 2 Bob 89 94
3 4 Eric 78 94
4 5 Helen 97 94
6 7 Iricss 99 91
7 7 Iric 99 91

groupby方法

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
df = pd.DataFrame({'key1':list('ababa'),
'key2': ['one','two','one','two','one'],
'data1': np.random.randn(5),
'data2': np.random.randn(5)})
print(df)

data1 data2 key1 key2
0 -1.313101 -0.453361 a one
1 0.791463 1.096693 b two
2 0.462611 1.150597 a one
3 -0.216121 1.381333 b two
4 0.077367 -0.282876 a one

df.groupby('key1').mean()
data1 data2
key1
a -0.257707 0.138120
b 0.287671 1.239013
#可以看出没有key2列,因为df[‘key2’]不是数值数据,所以被从结果中移除。默认情况下,所有数值列都会被聚合,虽然有时可能被过滤为一个子集。

删除

1、删除列

test_dict_df.drop(columns=['name'])

2、删除行

drop这边不支持切片写法

test_dict_df.drop([0:4])

只能

test_dict_df.drop([0,1,2,3,4])

和append一样,函数返回的都是一个新的DataFrame,要在源DataFrame上进行操作就得加上inplace=True,否则不会在test_dict_df上改动,要么就把新的DataFrame赋给源DataFrame。

修改

和前面提到的一样loc会直接覆盖掉原有的值

数值修改

1、对列

test_dict_df.loc[:,('english','id')]=[[90,1],[80,2],[80,2],[80,2],[80,2],[80,2]]

2、对行

test_dict_df.loc[0:1,('english','id','math','name')]=[[90,1,100,'Alice_m'],[70,2,100,'Bob']]

3、对某个行列区域

综合下对行列的操作,合并一下

test_dict_df.loc[1:2,('english','id')]=[[38,2],[23,2]]

列名修改

test_dict_df.rename(columns={'english':'english_new', 'name':'name_new'},inplace=True)

索引修改

默认索引都是自动从0开始计数的,在表中最左边一列。修改部分索引的显示可以使用rename,譬如特别标记索引6和8对应的两列。

test_dict_df.rename({6:'star1', 8:'star2'},inplace=True)

设置其他列为索引

test_dict_df.set_index('id_new')