pandas数据处理
文章目录
- pandas数据处理
- 1、删除重复元素duplicated()
- 2. 映射
- 1) replace()函数:替换元素
- Series替换操作
- DataFrame替换操作
- 2) map()函数:新建一列
- 3) rename()函数:替换索引
- 3. 使用聚合操作对数据异常值检测和过滤
- 4. 排序
- 使用.take()函数排序
- 随机抽样
- 5. 数据分类处理【重点】
1、删除重复元素duplicated()
使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True(是重复的)
- 使用drop_duplicates()函数删除重复的行
- 使用duplicate()函数查看重复的行
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
data = [[100,100,100],[90,90,88],[100,100,100],[90,90,87],[100,100,100]]
columns = ['python','c++','java']
index = list('ABCDE')
df = DataFrame(data=data,index=index,columns=columns)
df
python | c++ | java | |
---|---|---|---|
A | 100 | 100 | 100 |
B | 90 | 90 | 88 |
C | 100 | 100 | 100 |
D | 90 | 90 | 87 |
E | 100 | 100 | 100 |
df.duplicated(keep="first") # 告诉我们 当前行是否重复
# 参数默认是 keep="first" 保留开始的 意思是如果发现很多重复的元素 第一个不算重复的 后面的才是 某一行重复 就返回True
结果为:
A
False
B
False
C
True
D
False
E
True
dtype: bool
df.duplicated(keep="last") # keep last 如果遇到重复的元素 最后一个不算重复的 前面的才算重复 这一行重复了 就是True
结果为:
A
True
B
False
C
True
D
False
E
False
dtype: bool
df.duplicated(keep=False) # 只要有和别人完全一样的 不管在开头还是结尾 都算重复 这一行如果是重复的就返回 True
结果为:
A
True
B
False
C
True
D
False
E
True
dtype: bool
df.drop_duplicates() # {'first', 'last', False}, default 'first'
python | c++ | java | |
---|---|---|---|
A | 100 | 100 | 100 |
B | 90 | 90 | 88 |
D | 90 | 90 | 87 |
df.drop_duplicates(keep="last")
python | c++ | java | |
---|---|---|---|
B | 90 | 90 | 88 |
D | 90 | 90 | 87 |
E | 100 | 100 | 100 |
df.drop_duplicates(keep=False)
python | c++ | java | |
---|---|---|---|
B | 90 | 90 | 88 |
D | 90 | 90 | 87 |
2. 映射
映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定
包含三种操作:
- replace()函数:替换元素
- 最重要:map()函数:新建一列
- rename()函数:替换索引
1) replace()函数:替换元素
使用replace()函数,对values进行替换操作
Series替换操作
- 单值替换
- 普通替换
- 字典替换(推荐)
- 多值替换
- 列表替换
- 字典替换(推荐)
s1 = Series(data = [100,'peppa',np.nan,'chengdu'])
s1
结果为:
0
100
1
peppa
2
NaN
3
chengdu
dtype: objec
单值替换 普通替换
s1.replace(to_replace="peppa",value="佩琪")
结果为:
0
100
1
佩琪
2
NaN
3
chengdu
dtype: object
单值替换 字典替换( )
s1.replace({"chengdu":"成都"})
结果为:
0
100
1
peppa
2
NaN
3
成都
dtype: object
多值替换 列表替换 s1.replace([要替换的值1,要替换的值2,…],[替换成什么1,替换成什么2,…])
s1.replace([100,np.nan],["满分","空值"])
结果为:
0
满分
1
peppa
2
空值
3
chengdu
dtype: object
多值替换 字典替换( { 要替换的值:替换成什么,要替换的值:替换成什么 } )
s1.replace({100:"满分","peppa":"佩琪"})
结果为:
0
满分
1
佩琪
2
NaN
3
chengdu
dtype: object
Series参数说明:
- method:对指定的值使用相邻的值填充
- limit:设定填充次数
s2 = Series(data=np.array([80,100,100,100,89,78]))
s2
结果为:
0
80
1
100
2
100
3
100
4
89
5
78
dtype: int32
如果指定value不好 还可以找值来填充
s2.replace(to_replace=100,method="bfill") # 从后面找值来替换当前值
结果为:
0
80
1
89
2
89
3
89
4
89
5
78
dtype: int32
s2.replace(to_replace=100,method="ffill") # 从前面找
结果为:
0
80
1
80
2
80
3
80
4
89
5
78
dtype: int32
s2.replace(to_replace=100,method="ffill",limit=1) # limit 指定是最多往前或者往后找几个, 如果找不到就不填充了 ,limit 默认是None不限制
结果为:
0
80
1
80
2
100
3
100
4
89
5
78
dtype: int32
DataFrame替换操作
-
单值替换
- 普通替换
- 按列指定单值替换{列标签:目标值}
-
多值替换
- 列表替换
- 单字典替换(推荐)
df = pd.read_excel("../data/data.xls",sheet_name=0)
df
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 甲 | NaN | NaN | NaN | Beijing |
B | 乙 | 69.0 | 142.0 | 29 | Beijing |
C | 丙 | 111.0 | 7.0 | 2 | Beijing |
D | 丁 | 139.0 | 19.0 | 125 | shanghai |
E | 戊 | 12.0 | 66.0 | Beijing | shanghai |
普通的单值替换
df.replace(to_replace='Beijing',value='北京')
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 甲 | NaN | NaN | NaN | 北京 |
B | 乙 | 69.0 | 142.0 | 29 | 北京 |
C | 丙 | 111.0 | 7.0 | 2 | 北京 |
D | 丁 | 139.0 | 19.0 | 125 | shanghai |
E | 戊 | 12.0 | 66.0 | 北京 | shanghai |
按列指定单值换目标值 ({列索引,待替换值},目标值)
df.replace({4:'Beijing'},'首都')
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 甲 | NaN | NaN | NaN | 首都 |
B | 乙 | 69.0 | 142.0 | 29 | 首都 |
C | 丙 | 111.0 | 7.0 | 2 | 首都 |
D | 丁 | 139.0 | 19.0 | 125 | shanghai |
E | 戊 | 12.0 | 66.0 | Beijing | shanghai |
多值替换 列表替换,replace([要替换的1,要替换的2…],[替换成1,替换成2])
df.replace([66,'甲','shanghai'],[100,'first','上海'])
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | first | NaN | NaN | NaN | Beijing |
B | 乙 | 69.0 | 142.0 | 29 | Beijing |
C | 丙 | 111.0 | 7.0 | 2 | Beijing |
D | 丁 | 139.0 | 19.0 | 125 | 上海 |
E | 戊 | 12.0 | 100.0 | 北京 | 上海 |
多值替换 字典替换,replace({要替换的1:替换成的值1,要替换的2:替换成的值2,…}) 可以将没有的值也放在这里 不会报错 将来可以整个项目使用一个过滤器,我们可以在 字典里面写很多值 字典中的值即使找不到也不会报错
df.replace({66:100,'乙':'second','Beijing':'BEIJING','没有的值':'也可以放'})
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
A | 甲 | NaN | NaN | NaN | BEIJING |
B | second | 69.0 | 142.0 | 29 | BEIJING |
C | 丙 | 111.0 | 7.0 | 2 | BEIJING |
D | 丁 | 139.0 | 19.0 | 125 | shanghai |
E | 戊 | 12.0 | 100.0 | BEIJING | shanghai |
注意:DataFrame中,无法使用method和limit参数
============================================
练习19:
假设张三李四的成绩单里有满分的情况,老师认为是作弊,把所有满分的情况(包括150,300分)都记0分,如何实现?
============================================
data = [[150,300],[150,300]]
index = ["张三","李四"]
columns = ["数学","理综"]
df = DataFrame(data,index,columns)
df
数学 | 理综 | |
---|---|---|
张三 | 150 | 300 |
李四 | 150 | 300 |
替换多个
df.replace({150:0,300:0})
df.replace([150,300],[0,0])
数学 | 理综 | |
---|---|---|
张三 | 0 | 0 |
李四 | 0 | 0 |
单值替换
df1 = df.replace(to_replace=150,value=0)
df1 = df.replace({"数学":150},0)
数学 | 理综 | |
---|---|---|
张三 | 0 | 300 |
李四 | 0 | 300 |
df1.replace(to_replace=300,value=0)
df1.replace({"理综":300},0)
数学 | 理综 | |
---|---|---|
张三 | 0 | 300 |
李四 | 0 | 300 |
2) map()函数:新建一列
- map(字典) 字典的键要足以匹配所有的数据,否则出现NaN
- map()可以映射新一列数据
- map()中可以使用lambd表达式
- map()中可以使用方法,可以是自定义的方法
注意 map()中不能使用sum之类的函数,for循环
score = pd.read_excel('./data.xls',sheet_name=1)
score
姓名 | 语文 | 数学 | python | php | |
---|---|---|---|---|---|
0 | 小明 | 90 | 98 | 90 | 98 |
1 | 小红 | 44 | 89 | 44 | 89 |
2 | 小芳 | 98 | 90 | 90 | 98 |
3 | 小李 | 89 | 44 | 44 | 89 |
4 | 李元芳 | 78 | 98 | 98 | 87 |
5 | 狄仁杰 | 66 | 44 | 44 | 89 |
映射字典
map_dic = {'小明':'北京','小红':'上海','小芳':'北京',
'小李':'广州','李元芳':'成都','狄仁杰':'成都'}
map函数不是DataFrame的方法,而是Sereis对象的方法, 可以传入映射字典
score["姓名"].map(map_dic)
结果为:
0
北京
1
上海
2
北京
3
广州
4
成都
5
成都
Name: 姓名, dtype: object
score["所在城市"] = score["姓名"].map(map_dic) # 可以传入字典
score
姓名 | 语文 | 数学 | python | php | 所在城市 | |
---|---|---|---|---|---|---|
0 | 小明 | 90 | 98 | 90 | 98 | 北京 |
1 | 小红 | 44 | 89 | 44 | 89 | 上海 |
2 | 小芳 | 98 | 90 | 90 | 98 | 北京 |
3 | 小李 | 89 | 44 | 44 | 89 | 广州 |
4 | 李元芳 | 78 | 98 | 98 | 87 | 成都 |
5 | 狄仁杰 | 66 | 44 | 44 | 89 | 成都 |
还可以传入 拉姆达表达式 如 lambda x:x+10
score["python"]= score["python"].map(lambda x:x+10)
score
#python数据加10
姓名 | 语文 | 数学 | python | php | 所在城市 | |
---|---|---|---|---|---|---|
0 | 小明 | 90 | 98 | 100 | 98 | 北京 |
1 | 小红 | 44 | 89 | 54 | 89 | 上海 |
2 | 小芳 | 98 | 90 | 100 | 98 | 北京 |
3 | 小李 | 89 | 44 | 54 | 89 | 广州 |
4 | 李元芳 | 78 | 98 | 108 | 87 | 成都 |
5 | 狄仁杰 | 66 | 44 | 54 | 89 | 成都 |
还可以传入自定义函数
def fn(x):
return x-20
score["php"]= score["php"].map(fn) #这里一定要注意,是把函数名传入,千万不要加小括号去调用
score
姓名 | 语文 | 数学 | python | php | 所在城市 | |
---|---|---|---|---|---|---|
0 | 小明 | 90 | 98 | 100 | 18 | 北京 |
1 | 小红 | 44 | 89 | 54 | 9 | 上海 |
2 | 小芳 | 98 | 90 | 100 | 18 | 北京 |
3 | 小李 | 89 | 44 | 54 | 9 | 广州 |
4 | 李元芳 | 78 | 98 | 108 | 7 | 成都 |
5 | 狄仁杰 | 66 | 44 | 54 | 9 | 成都 |
data = np.random.randint(0,150,size=(5,3))
columns = ['python','java','php']
index = ['peppa','mery','tom','jack','rose']
df = DataFrame(data,index,columns)
df
python | java | php | |
---|---|---|---|
peppa | 23 | 98 | 81 |
mery | 33 | 31 | 74 |
tom | 59 | 24 | 101 |
jack | 56 | 143 | 96 |
rose | 94 | 13 | 89 |
def map_score(x):
if x>120:
return "exellent"
elif x<90:
return "failed"
else:
return "pass"
df["phpx"]= df["php"].map(map_score)
df
python | java | php | phpx | |
---|---|---|---|---|
peppa | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed |
3) rename()函数:替换索引
对DataFrame的索引名进行更改,仍然是新建一个字典
score = pd.concat((df,df),keys=['A','B'],axis=1)
score
A | B | |||||||
---|---|---|---|---|---|---|---|---|
python | java | php | phpx | python | java | php | phpx | |
peppa | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
map_dic = {'peppa':'帅气','mery':'美丽','python':'蟒蛇',
'java':'咖啡','php':'拍黄片','A':'上','B':'下'}
score.rename(map_dic) # 默认是替换 行的名称
A | B | |||||||
---|---|---|---|---|---|---|---|---|
python | java | php | phpx | python | java | php | phpx | |
帅气 | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
美丽 | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
score.rename(columns=map_dic) # 指定columns可以对列名称进行替换
上 | 下 | |||||||
---|---|---|---|---|---|---|---|---|
蟒蛇 | 咖啡 | 拍黄片 | phpx | 蟒蛇 | 咖啡 | 拍黄片 | phpx | |
peppa | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
score.rename(columns=map_dic,level=0) # 通过level参数 可以指定具体对哪一层级进行替换
上 | 下 | |||||||
---|---|---|---|---|---|---|---|---|
python | java | php | phpx | python | java | php | phpx | |
peppa | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
score.rename(columns=map_dic,level=1) # 0 是最外层
A | B | |||||||
---|---|---|---|---|---|---|---|---|
蟒蛇 | 咖啡 | 拍黄片 | phpx | 蟒蛇 | 咖啡 | 拍黄片 | phpx | |
peppa | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
score.rename(columns=map_dic,level=-1)
A | B | |||||||
---|---|---|---|---|---|---|---|---|
蟒蛇 | 咖啡 | 拍黄片 | phpx | 蟒蛇 | 咖啡 | 拍黄片 | phpx | |
peppa | 23 | 98 | 81 | failed | 23 | 98 | 81 | failed |
mery | 33 | 31 | 74 | failed | 33 | 31 | 74 | failed |
tom | 59 | 24 | 101 | pass | 59 | 24 | 101 | pass |
jack | 56 | 143 | 96 | pass | 56 | 143 | 96 | pass |
rose | 94 | 13 | 89 | failed | 94 | 13 | 89 | failed |
使用rename()函数替换行索引
- index 替换行索引
- columns 替换列索引
- level 指定多维索引的维度
3. 使用聚合操作对数据异常值检测和过滤
使用 df.describe() 函数查看每一列的描述性统计量
data = np.random.randn(1000,5)
df = DataFrame(data)
df
df.describe()
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
count | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 | 1000.000000 |
mean | -0.041642 | 0.013773 | 0.014445 | 0.019873 | 0.042694 |
std | 1.025455 | 1.013594 | 0.983300 | 1.006718 | 0.968992 |
min | -2.977845 | -3.063590 | -3.032535 | -2.888868 | -3.191746 |
25% | -0.703325 | -0.712109 | -0.645296 | -0.644217 | -0.597502 |
50% | -0.054138 | 0.057187 | 0.001426 | 0.020060 | 0.057830 |
75% | 0.664146 | 0.704886 | 0.653665 | 0.690365 | 0.725881 |
max | 3.777147 | 3.113222 | 3.149599 | 3.305668 | 3.050308 |
使用std()函数可以求得DataFrame对象每一列的标准差
df.std()
结果为:
0
1.025455
1
1.013594
2
0.983300
3
1.006718
4
0.968992
dtype: float64
根据每一列或行的标准差,对DataFrame元素进行过滤。
借助any()或all()函数, 测试是否有True,有一个或以上返回True,反之返回False
对每一列应用筛选条件,去除标准差太大的数据
# 寻找异常数据 太大的 或者 太小的
df.mean() # 各个列的平均值 是一个Series
df - df.mean() # DataFrame - Series DataFrame中的每一行都和Series做减法 对应的列相减
df - df.mean() > 3*df.std()
(df - df.mean() > 3*df.std()).any()
(df - df.mean() > 3*df.std()).any(axis=1)
#
df[(df - df.mean() > 3*df.std()).any(axis=1)] #找到异常的行
删除特定索引df.drop(labels,inplace = True)
drop_idx = df[(df - df.mean() > 3*df.std()).any(axis=1)].index
df.drop(drop_idx).shape
============================================
练习:
新建一个形状为10000*3的标准正态分布的DataFrame(np.random.randn),去除掉所有满足以下情况的行:其中任一元素绝对值大于3倍标准差
============================================
4. 排序
使用.take()函数排序
- take()函数接受一个索引列表,用数字表示
- eg:df.take([1,3,4,2,5])
可以借助np.random.permutation()函数随机排序
data = np.random.randint(0,100,size=(5,5))
index = list('ABCDE')
columns = list('甲乙丙丁戊')
df = DataFrame(data=data,index=index,columns=columns)
df
甲 | 乙 | 丙 | 丁 | 戊 | |
---|---|---|---|---|---|
A | 19 | 22 | 59 | 34 | 79 |
B | 43 | 71 | 71 | 25 | 77 |
C | 46 | 63 | 43 | 14 | 66 |
D | 89 | 46 | 86 | 33 | 40 |
E | 36 | 79 | 66 | 68 | 67 |
df.take([3,2,1]) # 按照索引去取行 顺序随意 还可以重复 还可以不完全
甲 | 乙 | 丙 | 丁 | 戊 | |
---|---|---|---|---|---|
D | 89 | 46 | 86 | 33 | 40 |
C | 46 | 63 | 43 | 14 | 66 |
B | 43 | 71 | 71 | 25 | 77 |
df.take([3,3,3,3])
甲 | 乙 | 丙 | 丁 | 戊 | |
---|---|---|---|---|---|
D | 89 | 46 | 86 | 33 | 40 |
D | 89 | 46 | 86 | 33 | 40 |
D | 89 | 46 | 86 | 33 | 40 |
D | 89 | 46 | 86 | 33 | 40 |
np.random.permutation(5)
结果为:
array([3, 1, 4, 2, 0])
df.take(np.random.permutation(5)) # 随机排序 (行不会少 也不会重复 只是顺序随机变换)
甲 | 乙 | 丙 | 丁 | 戊 | |
---|---|---|---|---|---|
B | 43 | 71 | 71 | 25 | 77 |
D | 89 | 46 | 86 | 33 | 40 |
C | 46 | 63 | 43 | 14 | 66 |
A | 19 | 22 | 59 | 34 | 79 |
E | 36 | 79 | 66 | 68 | 67 |
随机抽样
当DataFrame规模足够大时,直接使用np.random.randint()函数,就配合take()函数实现随机抽样
df.take(np.random.randint(0,5,size=2)) # 随机抽样
甲 | 乙 | 丙 | 丁 | 戊 | |
---|---|---|---|---|---|
B | 43 | 71 | 71 | 25 | 77 |
C | 46 | 63 | 43 | 14 | 66 |
5. 数据分类处理【重点】
数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
- 分组:先把数据分为几组
- 用函数处理:为不同组的数据应用不同的函数以转换数据
- 合并:把不同组得到的结果合并起来
数据分类处理的核心:
- groupby()函数
- groups属性查看分组情况
In [547]:
df = DataFrame({'item':['苹果','香蕉','橘子','香蕉','橘子','苹果','苹果'],
'price':[4,3,3,2.5,4,2,2.8],
'color':['red','yellow','yellow','green','green','green','yello'],
'weight':[12,20,50,30,20,44,37]})
df
item | price | color | weight | |
---|---|---|---|---|
0 | 苹果 | 4.0 | red | 12 |
1 | 香蕉 | 3.0 | yellow | 20 |
2 | 橘子 | 3.0 | yellow | 50 |
3 | 香蕉 | 2.5 | green | 30 |
4 | 橘子 | 4.0 | green | 20 |
5 | 苹果 | 2.0 | green | 44 |
6 | 苹果 | 2.8 | yello | 37 |
- 根据item分组,通过groups属性查看结果
df.groupby("item").groups
结果为:
{'橘子': Int64Index([2, 4], dtype='int64'),
'苹果': Int64Index([0, 5, 6], dtype='int64'),
'香蕉': Int64Index([1, 3], dtype='int64')}
- 获取weight的总和
df.groupby("item")["weight"].sum() #各类水果的总重量
结果为:
item
橘子
70
苹果
93
香蕉
50
Name: weight, dtype: int64
- 把总和跟df进行merge合并
df2 = DataFrame(df.groupby("item")["weight"].sum())
df2
weight | |
---|---|
item | |
橘子 | 70 |
苹果 | 93 |
香蕉 | 50 |
pd.merge(df,df2,on="item",how="outer",suffixes=["","_total"])
item | price | color | weight | weight_total | |
---|---|---|---|---|---|
0 | 苹果 | 4.0 | red | 12 | 93 |
1 | 苹果 | 2.0 | green | 44 | 93 |
2 | 苹果 | 2.8 | yello | 37 | 93 |
3 | 香蕉 | 3.0 | yellow | 20 | 50 |
4 | 香蕉 | 2.5 | green | 30 | 50 |
5 | 橘子 | 3.0 | yellow | 50 | 70 |
6 | 橘子 | 4.0 | green | 20 | 70 |
最后
以上就是贤惠黑裤最近收集整理的关于05-1 pandas数据处理 删除duplicated()、替换replace(),映射map(),重命名rename()、聚合函数、排序take()、分组groupby()pandas数据处理的全部内容,更多相关05-1内容请搜索靠谱客的其他文章。
发表评论 取消回复