程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(1)

数据分析工具Pandas(7):数据清洗、合并、转化和重构

发布于2020-02-14 20:37     阅读(493)     评论(0)     点赞(30)     收藏(3)


数据分析工具Pandas(1):Pandas的数据结构

数据分析工具Pandas(2):Pandas的索引操作

数据分析工具Pandas(3):Pandas的对齐运算

数据分析工具Pandas(4):Pandas的函数应用

数据分析工具Pandas(5):Pandas的层级索引

数据分析工具Pandas(6):Pandas统计计算和描述


数据清洗

  • 数据清洗是数据分析关键的一步,直接影响之后的处理工作

  • 数据需要修改吗?有什么需要修改的吗?数据应该怎么调整才能适用于接下来的分析和挖掘?

  • 是一个迭代的过程,实际项目中可能需要不止一次地执行这些清洗操作

  • 处理缺失数据:pd.fillna(),pd.dropna()

数据连接(pd.merge)

  • pd.merge

  • 根据单个或多个键将不同DataFrame的行连接起来

  • 类似数据库的连接操作

 

  1. import pandas as pd
  2. import numpy as np
  3. df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
  4. 'data1' : np.random.randint(0,10,7)})
  5. df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
  6. 'data2' : np.random.randint(0,10,3)})
  7. print(df_obj1)
  8. print(df_obj2)

运行结果:

  1. data1 key
  2. data1 key
  3. 0 8 b
  4. 1 8 b
  5. 2 3 a
  6. 3 5 c
  7. 4 4 a
  8. 5 9 a
  9. 6 6 b
  10. data2 key
  11. 0 9 a
  12. 1 0 b
  13. 2 3 d

1. 默认将重叠列的列名作为“外键”进行连接

 

  1. # 默认将重叠列的列名作为“外键”进行连接
  2. print(pd.merge(df_obj1, df_obj2))

运行结果:

  1. data1 key data2
  2. 0 8 b 0
  3. 1 8 b 0
  4. 2 6 b 0
  5. 3 3 a 9
  6. 4 4 a 9
  7. 5 9 a 9

2. on显示指定“外键”

 

  1. # on显示指定“外键”
  2. print(pd.merge(df_obj1, df_obj2, on='key'))

运行结果:

  1. data1 key data2
  2. 0 8 b 0
  3. 1 8 b 0
  4. 2 6 b 0
  5. 3 3 a 9
  6. 4 4 a 9
  7. 5 9 a 9

3. left_on,左侧数据的“外键”,right_on,右侧数据的“外键”

 

  1. # left_on,right_on分别指定左侧数据和右侧数据的“外键”
  2. # 更改列名
  3. df_obj1 = df_obj1.rename(columns={'key':'key1'})
  4. df_obj2 = df_obj2.rename(columns={'key':'key2'})
  5. print(pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2'))

运行结果:

  1. data1 key1 data2 key2
  2. 0 8 b 0 b
  3. 1 8 b 0 b
  4. 2 6 b 0 b
  5. 3 3 a 9 a
  6. 4 4 a 9 a
  7. 5 9 a 9 a

默认是“内连接”(inner),即结果中的键是交集

how指定连接方式

4. “外连接”(outer),结果中的键是并集

 

  1. # “外连接”
  2. print(pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='outer'))

运行结果:

  1. data1 key1 data2 key2
  2. 0 8.0 b 0.0 b
  3. 1 8.0 b 0.0 b
  4. 2 6.0 b 0.0 b
  5. 3 3.0 a 9.0 a
  6. 4 4.0 a 9.0 a
  7. 5 9.0 a 9.0 a
  8. 6 5.0 c NaN NaN
  9. 7 NaN NaN 3.0 d

5. “左连接”(left)

 

  1. # 左连接
  2. print(pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='left'))

运行结果:

  1. data1 key1 data2 key2
  2. 0 8 b 0.0 b
  3. 1 8 b 0.0 b
  4. 2 3 a 9.0 a
  5. 3 5 c NaN NaN
  6. 4 4 a 9.0 a
  7. 5 9 a 9.0 a
  8. 6 6 b 0.0 b

6. “右连接”(right)

 

  1. # 右连接
  2. print(pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='right'))

运行结果:

  1. data1 key1 data2 key2
  2. 0 8.0 b 0 b
  3. 1 8.0 b 0 b
  4. 2 6.0 b 0 b
  5. 3 3.0 a 9 a
  6. 4 4.0 a 9 a
  7. 5 9.0 a 9 a
  8. 6 NaN NaN 3 d

7. 处理重复列名

suffixes,默认为_x, _y

 

  1. # 处理重复列名
  2. df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
  3. 'data' : np.random.randint(0,10,7)})
  4. df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
  5. 'data' : np.random.randint(0,10,3)})
  6. print(pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right')))

运行结果:

  1. data_left key data_right
  2. 0 9 b 1
  3. 1 5 b 1
  4. 2 1 b 1
  5. 3 2 a 8
  6. 4 2 a 8
  7. 5 5 a 8

8. 按索引连接

left_index=True或right_index=True

 

  1. # 按索引连接
  2. df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
  3. 'data1' : np.random.randint(0,10,7)})
  4. df_obj2 = pd.DataFrame({'data2' : np.random.randint(0,10,3)}, index=['a', 'b', 'd'])
  5. print(pd.merge(df_obj1, df_obj2, left_on='key', right_index=True))

运行结果:

  1. data1 key data2
  2. 0 3 b 6
  3. 1 4 b 6
  4. 6 8 b 6
  5. 2 6 a 0
  6. 4 3 a 0
  7. 5 0 a 0

数据合并(pd.concat)

  • 沿轴方向将多个对象合并到一起

1. NumPy的concat

np.concatenate

 

  1. import numpy as np
  2. import pandas as pd
  3. arr1 = np.random.randint(0, 10, (3, 4))
  4. arr2 = np.random.randint(0, 10, (3, 4))
  5. print(arr1)
  6. print(arr2)
  7. print(np.concatenate([arr1, arr2]))
  8. print(np.concatenate([arr1, arr2], axis=1))

运行结果:

  1. # print(arr1)
  2. [[3 3 0 8]
  3. [2 0 3 1]
  4. [4 8 8 2]]
  5. # print(arr2)
  6. [[6 8 7 3]
  7. [1 6 8 7]
  8. [1 4 7 1]]
  9. # print(np.concatenate([arr1, arr2]))
  10. [[3 3 0 8]
  11. [2 0 3 1]
  12. [4 8 8 2]
  13. [6 8 7 3]
  14. [1 6 8 7]
  15. [1 4 7 1]]
  16. # print(np.concatenate([arr1, arr2], axis=1))
  17. [[3 3 0 8 6 8 7 3]
  18. [2 0 3 1 1 6 8 7]
  19. [4 8 8 2 1 4 7 1]]

2. pd.concat

  • 注意指定轴方向,默认axis=0

  • join指定合并方式,默认为outer

  • Series合并时查看行索引有无重复

1) index 没有重复的情况

 

  1. # index 没有重复的情况
  2. ser_obj1 = pd.Series(np.random.randint(0, 10, 5), index=range(0,5))
  3. ser_obj2 = pd.Series(np.random.randint(0, 10, 4), index=range(5,9))
  4. ser_obj3 = pd.Series(np.random.randint(0, 10, 3), index=range(9,12))
  5. print(ser_obj1)
  6. print(ser_obj2)
  7. print(ser_obj3)
  8. print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))
  9. print(pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1))

运行结果:

  1. # print(ser_obj1)
  2. 0 1
  3. 1 8
  4. 2 4
  5. 3 9
  6. 4 4
  7. dtype: int64
  8. # print(ser_obj2)
  9. 5 2
  10. 6 6
  11. 7 4
  12. 8 2
  13. dtype: int64
  14. # print(ser_obj3)
  15. 9 6
  16. 10 2
  17. 11 7
  18. dtype: int64
  19. # print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))
  20. 0 1
  21. 1 8
  22. 2 4
  23. 3 9
  24. 4 4
  25. 5 2
  26. 6 6
  27. 7 4
  28. 8 2
  29. 9 6
  30. 10 2
  31. 11 7
  32. dtype: int64
  33. # print(pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1))
  34. 0 1 2
  35. 0 1.0 NaN NaN
  36. 1 5.0 NaN NaN
  37. 2 3.0 NaN NaN
  38. 3 2.0 NaN NaN
  39. 4 4.0 NaN NaN
  40. 5 NaN 9.0 NaN
  41. 6 NaN 8.0 NaN
  42. 7 NaN 3.0 NaN
  43. 8 NaN 6.0 NaN
  44. 9 NaN NaN 2.0
  45. 10 NaN NaN 3.0
  46. 11 NaN NaN 3.0

2) index 有重复的情况

 

  1. # index 有重复的情况
  2. ser_obj1 = pd.Series(np.random.randint(0, 10, 5), index=range(5))
  3. ser_obj2 = pd.Series(np.random.randint(0, 10, 4), index=range(4))
  4. ser_obj3 = pd.Series(np.random.randint(0, 10, 3), index=range(3))
  5. print(ser_obj1)
  6. print(ser_obj2)
  7. print(ser_obj3)
  8. print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))

运行结果:

  1. # print(ser_obj1)
  2. 0 0
  3. 1 3
  4. 2 7
  5. 3 2
  6. 4 5
  7. dtype: int64
  8. # print(ser_obj2)
  9. 0 5
  10. 1 1
  11. 2 9
  12. 3 9
  13. dtype: int64
  14. # print(ser_obj3)
  15. 0 8
  16. 1 7
  17. 2 9
  18. dtype: int64
  19. # print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))
  20. 0 0
  21. 1 3
  22. 2 7
  23. 3 2
  24. 4 5
  25. 0 5
  26. 1 1
  27. 2 9
  28. 3 9
  29. 0 8
  30. 1 7
  31. 2 9
  32. dtype: int64
  33. # print(pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1, join='inner'))
  34. # join='inner' 将去除NaN所在的行或列
  35. 0 1 2
  36. 0 0 5 8
  37. 1 3 1 7
  38. 2 7 9 9

3) DataFrame合并时同时查看行索引和列索引有无重复

 

  1. df_obj1 = pd.DataFrame(np.random.randint(0, 10, (3, 2)), index=['a', 'b', 'c'],
  2. columns=['A', 'B'])
  3. df_obj2 = pd.DataFrame(np.random.randint(0, 10, (2, 2)), index=['a', 'b'],
  4. columns=['C', 'D'])
  5. print(df_obj1)
  6. print(df_obj2)
  7. print(pd.concat([df_obj1, df_obj2]))
  8. print(pd.concat([df_obj1, df_obj2], axis=1, join='inner'))

运行结果:

  1. # print(df_obj1)
  2. A B
  3. a 3 3
  4. b 5 4
  5. c 8 6
  6. # print(df_obj2)
  7. C D
  8. a 1 9
  9. b 6 8
  10. # print(pd.concat([df_obj1, df_obj2]))
  11. A B C D
  12. a 3.0 3.0 NaN NaN
  13. b 5.0 4.0 NaN NaN
  14. c 8.0 6.0 NaN NaN
  15. a NaN NaN 1.0 9.0
  16. b NaN NaN 6.0 8.0
  17. # print(pd.concat([df_obj1, df_obj2], axis=1, join='inner'))
  18. A B C D
  19. a 3 3 1 9
  20. b 5 4 6 8

数据重构

1. stack

  • 将列索引旋转为行索引,完成层级索引

  • DataFrame->Series

 

  1. import numpy as np
  2. import pandas as pd
  3. df_obj = pd.DataFrame(np.random.randint(0,10, (5,2)), columns=['data1', 'data2'])
  4. print(df_obj)
  5. stacked = df_obj.stack()
  6. print(stacked)

运行结果:

  1. # print(df_obj)
  2. data1 data2
  3. 0 7 9
  4. 1 7 8
  5. 2 8 9
  6. 3 4 1
  7. 4 1 2
  8. # print(stacked)
  9. 0 data1 7
  10. data2 9
  11. 1 data1 7
  12. data2 8
  13. 2 data1 8
  14. data2 9
  15. 3 data1 4
  16. data2 1
  17. 4 data1 1
  18. data2 2
  19. dtype: int64

2. unstack

  • 将层级索引展开

  • Series->DataFrame

  • 认操作内层索引,即level=-1

 

  1. # 默认操作内层索引
  2. print(stacked.unstack())
  3. # 通过level指定操作索引的级别
  4. print(stacked.unstack(level=0))

运行结果:

  1. # print(stacked.unstack())
  2. data1 data2
  3. 0 7 9
  4. 1 7 8
  5. 2 8 9
  6. 3 4 1
  7. 4 1 2
  8. # print(stacked.unstack(level=0))
  9. 0 1 2 3 4
  10. data1 7 7 8 4 1
  11. data2 9 8 9 1 2

数据转换

一、 处理重复数据

duplicated() 返回布尔型Series表示每行是否为重复行

 

  1. import numpy as np
  2. import pandas as pd
  3. df_obj = pd.DataFrame({'data1' : ['a'] * 4 + ['b'] * 4,
  4. 'data2' : np.random.randint(0, 4, 8)})
  5. print(df_obj)
  6. print(df_obj.duplicated())

运行结果:

  1. # print(df_obj)
  2. data1 data2
  3. 0 a 3
  4. 1 a 2
  5. 2 a 3
  6. 3 a 3
  7. 4 b 1
  8. 5 b 0
  9. 6 b 3
  10. 7 b 0
  11. # print(df_obj.duplicated())
  12. 0 False
  13. 1 False
  14. 2 True
  15. 3 True
  16. 4 False
  17. 5 False
  18. 6 False
  19. 7 True
  20. dtype: bool

drop_duplicates() 过滤重复行

默认判断全部列

可指定按某些列判断

 

  1. print(df_obj.drop_duplicates())
  2. print(df_obj.drop_duplicates('data2'))

运行结果:

  1. # print(df_obj.drop_duplicates())
  2. data1 data2
  3. 0 a 3
  4. 1 a 2
  5. 4 b 1
  6. 5 b 0
  7. 6 b 3
  8. # print(df_obj.drop_duplicates('data2'))
  9. data1 data2
  10. 0 a 3
  11. 1 a 2
  12. 4 b 1
  13. 5 b 0

3. 根据map传入的函数对每行或每列进行转换

  • Series根据map传入的函数对每行或每列进行转换

示例代码:

  1. ser_obj = pd.Series(np.random.randint(0,10,10))
  2. print(ser_obj)
  3. print(ser_obj.map(lambda x : x ** 2))

运行结果:

  1. # print(ser_obj)
  2. 0 1
  3. 1 4
  4. 2 8
  5. 3 6
  6. 4 8
  7. 5 6
  8. 6 6
  9. 7 4
  10. 8 7
  11. 9 3
  12. dtype: int64
  13. # print(ser_obj.map(lambda x : x ** 2))
  14. 0 1
  15. 1 16
  16. 2 64
  17. 3 36
  18. 4 64
  19. 5 36
  20. 6 36
  21. 7 16
  22. 8 49
  23. 9 9
  24. dtype: int64

二、数据替换

replace根据值的内容进行替换

 

  1. # 单个值替换单个值
  2. print(ser_obj.replace(1, -100))
  3. # 多个值替换一个值
  4. print(ser_obj.replace([6, 8], -100))
  5. # 多个值替换多个值
  6. print(ser_obj.replace([4, 7], [-100, -200]))

运行结果:

  1. # print(ser_obj.replace(1, -100))
  2. 0 -100
  3. 1 4
  4. 2 8
  5. 3 6
  6. 4 8
  7. 5 6
  8. 6 6
  9. 7 4
  10. 8 7
  11. 9 3
  12. dtype: int64
  13. # print(ser_obj.replace([6, 8], -100))
  14. 0 1
  15. 1 4
  16. 2 -100
  17. 3 -100
  18. 4 -100
  19. 5 -100
  20. 6 -100
  21. 7 4
  22. 8 7
  23. 9 3
  24. dtype: int64
  25. # print(ser_obj.replace([4, 7], [-100, -200]))
  26. 0 1
  27. 1 -100
  28. 2 8
  29. 3 6
  30. 4 8
  31. 5 6
  32. 6 6
  33. 7 -100
  34. 8 -200
  35. 9 3
  36. dtype: int64

参考资料

 

发布了274 篇原创文章 · 获赞 456 · 访问量 40万+


所属网站分类: 技术文章 > 博客

作者:232hdsjdh

链接:https://www.pythonheidong.com/blog/article/231520/564b6c69007301e21988/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

30 0
收藏该文
已收藏

评论内容:(最多支持255个字符)