panda数据处理

转自:https://blog.csdn.net/Dorisi_H_n_q/article/details/82313244,进行了整理结合
其他常用的统计方法有:

常用统计方法

count 非 NA 值的数量
describe 针对 Series 或 DF 的列计算汇总统计
min , max 最小值和最大值
argmin , argmax 最小值和最大值的索引位置(整数)
idxmin , idxmax 最小值和最大值的索引值
quantile 样本分位数(0 到 1)
sum 求和
mean 均值
median 中位数
mad 根据均值计算平均绝对离差
var 方差
std 标准差
skew 样本值的偏度(三阶矩)
kurt 样本值的峰度(四阶矩)
cumsum 样本值的累计和
cummin , cummax 样本值的累计最大值和累计最小值
cumprod 样本值的累计积
diff 计算一阶差分(对时间序列很有用)
pct_change 计算百分数变化

1、删除重复元素

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True


 
 
  1. import numpy as np
  2. import pandas as pd
  3. from pandas import Series,DataFrame
  4. import matplotlib.pyplot as plt
  5. %matplotlib inline
  • 创建数据集:


 
 
  1. # color 0 :red;1:green;2:blue
  2. df = DataFrame({ 'color':np.random.randint( 0, 3,size = 300), 'num':np.random.randint( 0, 5,size = 300)})
  3. df
  4. #或者:
  5. b=np.random.choice([ 'B', 'M'],size=( 100, 2))
  6. b1=DataFrame(b,columns=[ 'True', 'Predict'])
  7. b1


 
 
  1. # 计算True的总个数,即计算重复的总行数
  2. df.duplicated().sum()
  3. Out: 285
  • 使用drop_duplicates()函数删除重复的行【inplace=True则会修改原数组】

df.drop_duplicates()
 
 

  • 查看图片中的重复元素

 
 
  1. img = plt.imread( './芝麻.jpg')
  2. img.shape
  3. Out: ( 662, 1000, 3)
  4. # 这张图片总共有多少个像素呢?
  5. # (红,绿,蓝)
  6. 662* 1000
  7. Out: 662000
  8. # numpy没有去重的方法
  9. img2 = img.reshape( -1, 3)
  10. img2
  11. # img2 必须是转化成n行n列,比如reshape(-1,3)
  12. df = DataFrame(img2,columns=[ 'red', 'green', 'blue'])
  13. df
  14. # 总数据662000
  15. # 非重复的像素,71526个 ,inplace=True则能修改原数组
  16. df.drop_duplicates().shape
  17. Out: ( 71526, 3)

【注意】如果使用pd.concat([df1,df2],axis = 1)生成新的DataFrame,新的df中columns相同,使用duplicate()和drop_duplicates()都会出问题

 

2. 映射

映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定

需要使用字典:

map = { 'label1':'value1', 'label2':'value2', ... }

包含三种操作:

  • replace()函数:替换元素
  • 最重要:map()函数:新建一列
  • rename()函数:替换索引

 

1) replace()函数:替换元素

使用replace()函数,对values进行替换操作

  • 定义数据集

 
 
  1. df = DataFrame({ 'color':np.random.randint( 0, 3,size = 300), 'num':np.random.randint( 10, 30,size = 300)})
  2. df

  • 首先定义一个字典
m = {0:'red',1:'green',2:'blue'}
 
 
  • 调用.replace()

 
 
  1. # replace方法,可将DataFrame中所有满足条件的数据,进行替换
  2. df.replace(m)

  • replace还经常用来替换NaN元素

 
 
  1. # 字典的key类型要一致
  2. m = { 0: 'red', 1: 'green', 2: 'blue', 1024: 'purple', 2048: 'cyan'}
  3. # 字典中映射关系,键值对,去DataFrame找数据,找到了就替换,没有找到,也不会报错
  4. df.replace(m)
  • 使用正则匹配替换:

数据集 data1 ——> 杂质:-数字\t

法①:遍历—> re.sub


 
 
  1. import re
  2. data1[ 0].map( lambda x: re.sub( '.*\d+\\t', '',x))

法②【一定要加上.str才能替换】:data1[0].str.replace

pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', '')) #用正则表达式修改数据
 
 

 

2) map()函数:新建一列

使用map()函数,由已有的列生成一个新列

适合处理某一单独的列。

仍然是新建一个字典

map()函数中可以使用lambda函数

transform()和map()类似

使用map()函数新建一个新列

 

  • 新建数据集

 
 
  1. df = DataFrame(np.random.randint( 0, 150,size = ( 10, 3)),
  2. columns=[ 'Python', 'Math', 'En'],index=list( 'ABCDEFGHJK'))
  3. df

  • map映射简单lambda函数

 
 
  1. # df['Python'] 10 个数据 迭代器
  2. df[ 'Java'] = df[ 'Python'].map( lambda x : 2*x - 100)
  3. df


 
 
  1. f = lambda x : x* 2 - 100
  2. type(f)
  3. Out: function
  4. def fun(x):
  5. x* 2 - 100
  6. type(fun)
  7. Out: function
  • 定义一个函数level,带入map函数:

 
 
  1. def convert(x):
  2. if x >= 130:
  3. return '优秀'
  4. elif x < 130 and x >= 100:
  5. return '良好'
  6. elif x < 100 and x >= 80:
  7. return '中等'
  8. elif x < 80 and x >= 60:
  9. return '及格'
  10. else:
  11. return '不及格'
  12. df[ 'Level'] = df[ 'Python'].map(convert)
  13. df

 

  • 给某一列都加上某个数:法① df['Python'] += 10

 
 
  1. # Python 这一列,老师出考题的时候,有一道题出错了,每个人Python加10分
  2. df[ 'Python'] += 10
  3. df

 

  • 给某一列都加上某个数:法② map(lambda x : x+10)

 
 
  1. # map 这个方法,可以修改当前的列
  2. df[ 'Python'] = df[ 'Python'].map( lambda x :x + 10)
  3. df
  • 分箱操作:

分箱、分块、分类——》

# 分箱,分类
# 葡萄品质0~10 
# 0~4 low
# 5~7 median
# 8~10 high


 
 
  1. # 分箱,分类
  2. # 葡萄品质0~10
  3. # 0~4 low
  4. # 5~7 median
  5. # 8~10 high
  6. # 0 ~ 10 信用
  7. # 0~3 low
  8. # 4~ 6 median
  9. # 7~10 high
  10. # 根据这个人手机产生数据
  11. def convert(x):
  12. if x >= 140:
  13. return 150
  14. elif x < 140 and x >= 100:
  15. return 125
  16. elif x < 100 and x>= 60:
  17. return 80
  18. else:
  19. return 0
  20. df[ 'Python'] = df[ 'Python'].map(convert)
  21. df

 

3) rename()函数:替换索引

  • 新建数据集:

 
 
  1. df = DataFrame(np.random.randint( 0, 150,size = ( 4, 3)))
  2. df

  • 仍然是新建一个字典,使用rename()函数替换行索引

 
 
  1. # 更改列标题 【axis = 0 行】
  2. m = { 0: '张三', 1: '李四', 2: '王五', 3: '小刘'}
  3. df.rename(m,axis = 0,inplace= True)
  4. # 更改行标题
  5. m = { 0: 'Python', 1: 'Math', 2: 'En'}
  6. df.rename(m,axis = 1,inplace= True)
  7. df

 

3. 异常值检测和过滤

使用describe()函数查看每一列的描述性统计量

  • 新建数据集

 
 
  1. df = DataFrame(np.random.randn( 10000, 3),columns=list( 'ABC'))
  2. df

  • 检测异常值:① 求出每一列均值;② 异常值判断条件:大于5倍均值

 
 
  1. # 过滤条件,大于5倍平均,异常
  2. # 均值0.79,则大于3.95为异常值
  3. df.abs().mean()
  4. Out:
  5. A 0.798357
  6. B 0.793909
  7. C 0.789348
  8. dtype: float64
  9. # 找出各个属性的异常值
  10. cond = df.abs() > 3.95
  11. cond.sum()
  12. Out:
  13. A 2
  14. B 2
  15. C 0
  16. dtype: int64
  17. # 异常值总和
  18. (cond.sum()).sum()
  19. # 异常值总行数
  20. cond.any(axis = 1).sum()
  21. Out: 4
  22. # 以DataFrame形式展示存在异常值的行数
  23. df[cond.any(axis = 1)]

展示满足要求的数据:


 
 
  1. # 满足要求的数据
  2. cond = df.abs() <= 3.95
  3. cond = cond.all(axis = 1)
  4. df[cond]

 

  • 使用std()函数可以求得DataFrame对象每一列的标准差;
  • 根据每一列的标准差,对DataFrame元素进行过滤;
  • 借助any()函数, 测试是否有True,有一个或以上返回True,反之返回False;
  • 对每一列应用筛选条件,去除标准差太大的数据

 

3原则:如果数据服从正态分布,在3原则下,异常值被定义为一组测定值中与平均值的偏差超过3倍标准差的值。在正态分布的假设下,距离平均值3之外的值出现的概率为P(|x-|>3)≤0.003,属于极个别的小概率事件。


 
 
  1. #平均值上下三倍标准差之间属于正常点
  2. std=df.abs().std()
  3. std
  4. Out:
  5. A 0.607076
  6. B 0.598781
  7. C 0.594652
  8. dtype: float64
  9. mean=df.abs().mean()
  10. mean
  11. Out:
  12. A 0.798357
  13. B 0.793909
  14. C 0.789348
  15. dtype: float64
  16. low=mean -3*std
  17. high=mean+ 3*std
  18. display(low.mean(),high.mean())
  19. Out:
  20. -1.0066372280404017
  21. 2.5943795581659246
  22. # 异常值 位于小于mean-3*std or 大于mean+3*std
  23. low1=df.abs()<low.mean()
  24. high1=df.abs() > high.mean()
  25. low_high1=np.logical_or(low1,high1)
  26. low_high1
  27. # 显示异常值个数
  28. df[low_high1.any(axis= 1)].shape
  29. Out: ( 259, 3)
  30. # 过滤掉正常值,显示异常值
  31. df[low_high1.any(axis= 1)]
  32. #平均值上下三倍标准差之间属于正常点
  33. lowcond=df.abs()>low.mean()
  34. highcond=df.abs() < high.mean()
  35. low_high=np.logical_and(lowcond,highcond)
  36. low_high
  37. # 过滤异常值,满足条件 df.mean()-3*df.std() ~ df.mean()+3*df.std()
  38. df[low_high.all(axis= 1)].shape
  39. Out: ( 9741, 3)
  40. df.shape
  41. Out:( 10000, 3)
  42. 259+ 9741= 10000
  • 新建数据集:身高、体重
  • 手动创建异常值
  • 判定异常值范围
  • 过滤异常值

 
 
  1. df =DataFrame(
  2. { 'height':np.random.randint( 150, 200, 1000),
  3. 'weight':np.random.randint( 50, 90,size = 1000)})
  4. df
  5. # 创造异常值
  6. # 每隔10个数据加一个300,比如第10个原本63,处理后变363,第20,30..一样
  7. df[ 'weight'][:: 10] + 300
  8. df
  9. # 判定异常值范围:
  10. # 体重的异常值:>300公斤
  11. cond = df[ 'weight'] < 300
  12. # 异常值筛选:给定条件(数据不同,条件不一样,根据数据属性来做选择)
  13. df[cond]

 

4. 排序及打乱下标随机排序

使用.take()函数排序,可以借助np.random.permutation()函数随机排序

df.take([100,300,210])
 
 


 
 
  1. # 产生5个0-4的随机数
  2. np.random.permutation( 5)
  3. Out: array([ 2, 0, 4, 3, 1])
  4. # 产生1000个0-999的随机数
  5. index = np.random.permutation( 1000)
  6. index
  7. type(index)
  8. Out: numpy.ndarray
  9. # 使用产生的随机数作为下标排序显示数据
  10. df.take(index)
  • 另一种产生n个 0 ~ n-1 的随机数

 
 
  1. # 产生1000个从0~999的升序数列
  2. index = np.arange( 1000)
  3. index
  4. # 打乱0~999的顺序数列
  5. np.random.shuffle(index)
  6. index
  7. display(type(index),index)
  8. Out: numpy.ndarray
  9. # 使用随机打乱的数列作为下标显示数据
  10. df.take(index)

随机抽样

当DataFrame规模足够大时,直接使用np.random.randint()函数,就配合take()函数实现随机抽样


 
 
  1. df = DataFrame(np.random.randn( 10000, 3),columns=list( 'ABC'))
  2. df
  3. df.size
  4. Out: 30000


 
 
  1. ss=np.random.randint( 0, 10000,size = 100)
  2. ss
  3. Out:
  4. array([ 4065, 9998, 4088, 2039, 4184, 1807, 1325, 1569, 6657, 2974, 3211,
  5. 2982, 8154, 7668, 6738, 7486, 4362, 105, 6373, 3119, 1261, 1648,
  6. 2962, 7112, 2243, 6014, 2211, 6357, 2032, 1761, 7664, 6734, 1882,
  7. 6126, 8942, 4872, 8935, 9207, 4533, 4558, 9922, 5127, 9340, 5148,
  8. 640, 8374, 5681, 1160, 325, 2469, 9823, 7114, 8228, 5019, 4217,
  9. 2901, 8420, 4888, 4274, 6595, 2289, 1446, 8035, 958, 736, 7005,
  10. 5490, 2752, 3260, 9686, 5241, 3165, 8381, 7885, 4582, 8015, 7215,
  11. 8430, 8921, 4957, 2419, 7912, 9510, 1614, 1102, 3070, 2390, 228,
  12. 3588, 829, 6808, 4883, 349, 1869, 2073, 1992, 9280, 1085, 5495,
  13. 5396])
  14. DataFrame(ss)[ 0].unique().size
  15. Out: 100
  16. # 可以直接使用random.randint 产生的数据来做下标随机抽取数据
  17. df.take(np.random.randint( 0, 10000,size = 100))

5. 数据聚合【重点】

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

数据分类处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心: groupby()函数

  • 创建数据集

 
 
  1. df = DataFrame({ 'item':np.random.randint( 0, 4, 50),
  2. 'level':np.random.randint( 0, 3,size = 50),
  3. 'price':np.random.randint( 1, 10,size = 50),
  4. 'sailer':np.random.randint( 0, 3,size = 50),
  5. 'weight':np.random.randint( 50, 100,size = 50)})
  6. df

 

  • 赋值转换

 
 
  1. # = 赋值 :使用map({字典集})
  2. df[ 'item'] = df[ 'item'].map({ 0: '萝卜', 1: '白菜', 2: '西红柿', 3: '黄瓜'})
  3. df[ 'level'] = df[ 'level'].map({ 0: '差', 1: '中', 2: '优'})
  4. df[ 'sailer'] = df[ 'sailer'].map({ 0: '张大妈', 1: '李大妈', 2: '赵大叔'})
  5. df

 

  • 聚合操作

 
 
  1. # 按 sailer,item分组,显示价格的最大值
  2. aa=df.groupby([ 'sailer', 'item'])[ 'price'].max()
  3. aa
  4. Out:[Series]
  5. sailer item
  6. 张大妈 白菜 8
  7. 萝卜 8
  8. 西红柿 9
  9. 黄瓜 2
  10. 李大妈 白菜 4
  11. 萝卜 6
  12. 西红柿 7
  13. 黄瓜 9
  14. 赵大叔 白菜 8
  15. 萝卜 9
  16. 西红柿 8
  17. 黄瓜 8
  18. Name: price, dtype: int32
  19. # 按等级,类别分组,显示价格和体重的最小值
  20. df.groupby([ 'level', 'item'])[ 'price', 'weight'].min()

  • 求总和

 
 
  1. weight_sum = df.groupby([ 'level'])[ 'weight'].sum()
  2. weight_sum
  3. Out:
  4. level
  5. 1570
  6. 790
  7. 1250
  8. Name: weight, dtype: int64

 
 
  1. weight_sum = DataFrame(weight_sum)
  2. weight_sum


 
 
  1. # 给表头修改名字
  2. weight_sum = weight_sum.rename({ 'weight': 'weight_sum'},axis = 1)
  3. weight_sum

 

  • 合并聚合表格【左连接:left_on='level',right_index=True】注意:没有right_index=True会报错

 
 
  1. df2 = df.merge(weight_sum,left_on= 'level',right_index= True)
  2. df2

  • 求平均价格

 
 
  1. price_mean = df.groupby([ 'item'])[ 'price'].mean()
  2. price_mean = DataFrame(price_mean)
  3. price_mean
  4. # 修改标题名称
  5. price_mean.columns = [ 'price_mean']
  6. price_mean

  • 合并聚合数据表格
df2.merge(price_mean,left_on='item',right_index=True)
 
 

============================================

练习23:

  • 假设菜市场张大妈在卖菜,有以下属性:
  • 菜品(item):萝卜,白菜,辣椒,冬瓜
  • 颜色(color):白,青,红
  • 重量(weight)
  • 价格(price)
  1. 要求以属性作为列索引,新建一个ddd
  2. 对ddd进行聚合操作,求出颜色为白色的价格总和
  3. 对ddd进行聚合操作,求出萝卜的所有重量(包括白萝卜,胡萝卜,青萝卜)以及平均价格
  4. 使用merge合并总重量及平均价格

============================================


 
 
  1. # 测试choice
  2. np.random.choice([ 0, 1, 2],size= 10)
  3. Out:
  4. array([ 1, 0, 1, 1, 0, 2, 2, 1, 2, 2])
  • 创建数据集

 
 
  1. ddd=DataFrame({ 'item':np.random.choice([ '萝卜', '白菜', '辣椒', '冬瓜'],size= 50),
  2. 'color':np.random.choice([ '白', '青', '红'],size= 50),
  3. 'weight':np.random.randint( 10, 100, 50),
  4. 'price':np.random.randint( 1, 10, 50)
  5. })
  6. ddd

  • 求出颜色为白色的价格总和

 
 
  1. ddd.color.map( lambda x:x== '白').sum()
  2. Out: 19
  • 对ddd进行聚合操作,求出萝卜的所有重量(包括白萝卜,胡萝卜,青萝卜)以及平均价格

 
 
  1. p=ddd.groupby( 'item')[ 'price'].mean()
  2. p=DataFrame(p)
  3. p
  4. p.index
  5. Out: Index([ '冬瓜', '白菜', '萝卜', '辣椒'], dtype= 'object', name= 'item')
  6. p.columns
  7. Out: Index([ 'price'], dtype= 'object')
  8. w=ddd.groupby( 'item')[ 'weight'].sum()
  9. w=DataFrame(w)
  10. w

  • 使用merge合并总重量及平均价格
p.merge(w,left_index=True,right_index=True)
 
 

p.join(w)
 
 

============================================

6.0 高级数据聚合

可以使用pd.merge()函数将聚合操作的计算结果添加到df的每一行
使用groupby分组后调用加和等函数进行运算,让后最后可以调用add_prefix(),来修改列名

可以使用transform和apply实现相同功能

在transform或者apply中传入函数即可

  • 采用上面的数据集

  • 使用apply
df.groupby(['sailer','item'])['price'].apply(np.mean)
 
 

  • 使用transform

 
 
  1. # apply和transform都可以进行分组计算,计算结果一样
  2. # 表现形式不同,apply多层索引,图形直观,简洁
  3. # transform 一层索引,所有的数据,级联方便
  4. mean_price = df.groupby([ 'sailer', 'item'])[[ 'price']].transform(np.mean).add_prefix( 'mean_')
  5. mean_price

  • 使用pd.concat()拼接mean_price
pd.concat([df,mean_price],axis = 1)
 
 

 

transform()与apply()函数还能传入一个函数或者lambda


 
 
  1. df = DataFrame({ 'color':[ 'white', 'black', 'white', 'white', 'black', 'black'],
  2. 'status':[ 'up', 'up', 'down', 'down', 'down', 'up'],
  3. 'value1':[ 12.33, 14.55, 22.34, 27.84, 23.40, 18.33],
  4. 'value2':[ 11.23, 31.80, 29.99, 31.18, 18.25, 22.44]})

 

举栗子


 
 
  1. dic = {
  2. 'item':[ '萝卜', '白菜', '萝卜', '辣椒', '冬瓜', '冬瓜', '萝卜', '白菜'],
  3. 'color':[ 'red', 'white', 'green', 'red', 'green', 'white', 'white', 'green'],
  4. 'weight':[ 12, 30, 16, 5, 10, 5, 25, 18],
  5. 'price':[ 2.5, 0.8, 3.5, 4, 1.2, 1.5, 0.9, 3]
  6. }
  7. df = DataFrame(data=dic)
  8. df

定义函数


 
 
  1. # 定义求和
  2. def m_sum(items):
  3. sum= 0
  4. for item in items:
  5. sum+=item
  6. return sum
  7. # 定义求平均
  8. def my_mean(items): #参数为复数(List形式)
  9. sum= 0
  10. for item in items:
  11. sum+=item
  12. return sum/items.size

 
 
  1. df.groupby(by= 'item')[ 'weight'].apply(m_sum)[ '萝卜']
  2. Out:
  3. 53
  4. df.groupby(by= 'item')[ 'price'].apply(my_mean)
  5. Out:
  6. item
  7. Apple 3.00
  8. Banana 2.75
  9. Orange 3.50
  10. Name: price, dtype: float64

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值