1. Series 和 Dataframe
pandas的基本数据结构有两个:Series 和 Dataframe
Series 是一维数据结构,它由index和value组成。例如
import pandas as pd
obj=pd.Series([1,2,3,4])
print(obj[1], obj.values)
'''
1 [1 2 3 4]
'''
Dataframe 是一个二维结构,除了拥有index和value之外,还拥有columns。例如:
import pandas as pd
d=[[1,2,3,4],[5,6,7,8]]
index=["one","two"]
df=pd.DataFrame(d, index=index)
print(df.loc["one"])
'''
0 1
1 2
2 3
3 4
Name: one, dtype: int64
'''
2. 对行/列的相关操作
在正式开始之前,我们先区分一下后面会用到的几个操作: loc, iloc, ix
loc:通过选取行(列)标签索引数据;
iloc:通过选取行(列)位置编号索引数据;
ix:既可以通过行(列)标签索引数据,也可以通过行(列)位置编号索引数据。
是不是有点懵~~~ 那什么是标签,什么是位置编号呢? 请看下面的例子
import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(9).reshape(3,3),index=['ind0','ind1','ind2'],columns=['苹果','橙子','草莓'])
print(df)
'''
苹果 橙子 草莓
ind0 0 1 2
ind1 3 4 5
ind2 6 7 8
'''
上面的例子来说,
标签就是‘ind0’, 'ind1', 'ind2', '草莓’, ‘苹果’, '橙子'。即定义的index和column的名称
位置编号类似于列表中1,2,3 ...的编号。上面的例子中ind0的位置编号是0, ind2的位置编号是2。同样,‘苹果’的位置编号是0, ‘草莓’的位置编号是2。
loc 只能通过标签索引数据。 虽然都是标签索引,注意区分行和列的不同
import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(9).reshape(3,3),index=['ind0','ind1','ind2'],columns=['苹果','橙子','草莓'])
df.loc['ind0'] # 索引行
'''
苹果 0
橙子 1
草莓 2
Name: ind0, dtype: int32
'''
df.loc[:, '苹果'] # 索引列
'''
ind0 0
ind1 3
ind2 6
Name: 苹果, dtype: int32
'''
iloc 是通过位置编号索引, 只是把上面loc中的索引改为位置编号即可
df.iloc[0] # 行索引
'''
苹果 0
橙子 1
草莓 2
Name: ind0, dtype: int32
'''
df.iloc[:, 0] # 列索引
'''
ind0 0
ind1 3
ind2 6
Name: 苹果, dtype: int32
'''
ix 既可以通过标签索引又可以通过位置编号索引。但是但是但是,0.25.1版本已经不推荐使用ix了!
以下详细叙述pandas数据处理过程中可能碰到的集中情况:(无论哪种情况,你都可以用loc或者iloc)
2.1 截取单行/列
import numpy as np
import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(25).reshape(5,5),index=['ind0','ind1','ind2', 'ind3', 'ind4'],columns=['苹果','橙子','草莓', '西瓜', '葡萄'])
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 0 1 2 3 4
ind1 5 6 7 8 9
ind2 10 11 12 13 14
ind3 15 16 17 18 19
ind4 20 21 22 23 24
'''
# 行
rows_name = df.index.values.tolist()
# 方法1
row1 = df[0:1] # 注意是左闭右开
# 方法2
row2 = df.loc[rows_name[0]]
# 方法3
row3 = df.iloc[0]
'''
row1, row2, row3的输出均为:
苹果 橙子 草莓 西瓜 葡萄
0 1 2 3 4
'''
# 列
cols_name = df.columns.values.tolist()
# 方法1
col1 = df['苹果']
# 方法2
col2 = df[['苹果']]
# 方法3
col3 = df.loc[:, cols_name[0]]
# 方法4
col4 = df.iloc[:, 0]
'''
col1, col2, col3, col4的输出结果相同,取数据第一列:
ind0 0
ind1 5
ind2 10
ind3 15
ind4 20
Name: 苹果, dtype: int32
'''
2. 2 截取多行/列
rows_name = df.index.values.tolist()
'''
['ind0', 'ind1', 'ind2', 'ind3', 'ind4']
'''
# 2, 3, 4 行
# 方法1
mul_rows1 = df[1:4]
# 方法2
mul_rows2 = df.loc[rows_name[1]:rows_name[3]]
# 方法3
mul_rows3 = df.iloc[1:4]
# 方法4
mul_rows4 = df.loc[rows_name[1:4],:]
'''
输出结果为
苹果 橙子 草莓 西瓜 葡萄
ind1 5 6 7 8 9
ind2 10 11 12 13 14
ind3 15 16 17 18 19
'''
# 多列
# 方法1
mul_cols1 = df.loc[:, cols_name[1]:cols_name[3]] # 注意索引号,左闭右闭
# 方法2
mul_cols2 = df.iloc[:, 1:4] # 左闭右开
'''
橙子 草莓 西瓜
ind0 1 2 3
ind1 6 7 8
ind2 11 12 13
ind3 16 17 18
ind4 21 22 23
'''
2.3 提取切片数据
# 方法1:
df.loc['ind1':'ind3', '橙子':'西瓜']
# 方法2
df.iloc[1:4, 1:4]
'''
输出结果相同
橙子 草莓 西瓜
ind1 6 7 8
ind2 11 12 13
ind3 16 17 18
'''
2.4 删除行/列
# 删除行
# 方法1
df.drop(['ind0', 'ind1'])
# 方法2
df.drop(rows_name[0:2])
# 方法3
df.drop(index=['ind0', 'ind1'])
# 方法4
df.drop(index=rows_name[0:2])
'''
苹果 橙子 草莓 西瓜 葡萄
ind2 10 11 12 13 14
ind3 15 16 17 18 19
ind4 20 21 22 23 24
'''
# 删除列
# 方法1
df.drop(['苹果', '橙子'], axis=1)
# 方法2
df.drop(columns=['苹果', '橙子'])
# 方法3
df.drop(cols_name[0:2], axis=1)
# 方法4
df.drop(columns=cols_name[0:2])
'''
草莓 西瓜 葡萄
ind0 2 3 4
ind1 7 8 9
ind2 12 13 14
ind3 17 18 19
ind4 22 23 24
'''
2.5 增加行/列
# 增加单行
df.loc['new_row'] = df.loc['ind0']
'''
苹果 橙子 草莓 西瓜 葡萄 new_col
ind0 0 1 2 3 4 0
ind1 5 6 7 8 9 5
ind2 10 11 12 13 14 10
ind3 15 16 17 18 19 15
ind4 20 21 22 23 24 20
new_row 0 1 2 3 4 0
'''
# 增加单列
df['new_col'] = df['苹果']
'''
苹果 橙子 草莓 西瓜 葡萄 new_col
ind0 0 1 2 3 4 0
ind1 5 6 7 8 9 5
ind2 10 11 12 13 14 10
ind3 15 16 17 18 19 15
ind4 20 21 22 23 24 20
'''
# 增加多行
df.append(df[0:2])
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 0 1 2 3 4
ind1 5 6 7 8 9
ind2 10 11 12 13 14
ind3 15 16 17 18 19
ind4 20 21 22 23 24
ind0 0 1 2 3 4
ind1 5 6 7 8 9
'''
# 增加多列
df = df.assign(**{'col_new_1': df.loc[:,'苹果'].values, 'col2_new_2': df.loc[:, '橙子'], 'col3_new_3': 3})
'''
如果只是用df.assign()增加新列,不能改变原df数据,必须对df重新赋值
苹果 橙子 草莓 西瓜 葡萄 col_new_1 col2_new_2 col3_new_3
ind0 0 1 2 3 4 0 1 3
ind1 5 6 7 8 9 5 6 3
ind2 10 11 12 13 14 10 11 3
ind3 15 16 17 18 19 15 16 3
ind4 20 21 22 23 24 20 21 3
'''
2.6 重新赋值行/列
df[0:1] = df[1:2]
'''
注意,如果直接等,会出现赋值行/列为NaN的情况
苹果 橙子 草莓 西瓜 葡萄
ind0 NaN NaN NaN NaN NaN
ind1 5.0 6.0 7.0 8.0 9.0
ind2 10.0 11.0 12.0 13.0 14.0
ind3 15.0 16.0 17.0 18.0 19.0
ind4 20.0 21.0 22.0 23.0 24.0
'''
# 正确的做法
df[0:1] = df[1:2].values
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 5.0 6.0 7.0 8.0 9.0
ind1 5.0 6.0 7.0 8.0 9.0
ind2 10.0 11.0 12.0 13.0 14.0
ind3 15.0 16.0 17.0 18.0 19.0
ind4 20.0 21.0 22.0 23.0 24.0
'''
# 替换一整列
df['苹果'] = df['葡萄'].values
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 4 1 2 3 4
ind1 9 6 7 8 9
ind2 14 11 12 13 14
ind3 19 16 17 18 19
ind4 24 21 22 23 2
'''
2.7 拼接行/列
'''
'''
2.8 行/列数据操作
2.8.1 根据条件替换某一列/行中的某些值 (比如生成分类任务标签值)
# 方法一:
df['苹果'].loc[df['苹果'] < 10] = 0
df['苹果'].loc[df['苹果'] >= 10] = 1
# 方法二:
df['苹果'] = np.where(df.苹果 < 10, 0, 1)
# 方法三:
df.loc[df['苹果']<10, '苹果'] = 0
df.loc[df['苹果']>=10, '苹果'] = 1
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 0 1 2 3 4
ind1 0 6 7 8 9
ind2 1 11 12 13 14
ind3 1 16 17 18 19
ind4 1 21 22 23 24
'''
2.8.2. 对某一列/n列进行归一化操作
max_min_scaler = lambda x: (x - np.min(x)) / (np.max(x) - np.min(x))
df.loc[:, '苹果':'橙子'] = df.loc[:, '苹果':'橙子'].apply(max_min_scaler)
'''
苹果 橙子 草莓 西瓜 葡萄
ind0 0.00 0.00 2 3 4
ind1 0.25 0.25 7 8 9
ind2 0.50 0.50 12 13 14
ind3 0.75 0.75 17 18 19
ind4 1.00 1.00 22 23 24
'''
2.8.3. 将某一列设为index
'''
注意以下两种方式的区别
'''
# 方法1:
df.set_index('苹果')
'''
橙子 草莓 西瓜 葡萄
苹果
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
'''
# 方法2:
df.set_index(df['苹果'])
'''
苹果 橙子 草莓 西瓜 葡萄
苹果
0 0 1 2 3 4
5 5 6 7 8 9
10 10 11 12 13 14
15 15 16 17 18 19
20 20 21 22 23 24
'''
# 即方法2不会删除设为index的列