千家信息网

数据清洗、合并、转化和重构

发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,数据清洗数据清洗是数据分析关键的一步,直接影响之后的处理工作数据需要修改吗?有什么需要修改的吗?数据应该怎么调整才能适用于接下来的分析和挖掘?是一个迭代的过程,实际项目中可能需要不止一次地执行这些清洗
千家信息网最后更新 2025年01月24日数据清洗、合并、转化和重构

数据清洗

  • 数据清洗是数据分析关键的一步,直接影响之后的处理工作
  • 数据需要修改吗?有什么需要修改的吗?数据应该怎么调整才能适用于接下来的分析和挖掘?
  • 是一个迭代的过程,实际项目中可能需要不止一次地执行这些清洗操作
  • 处理缺失数据:pd.fillna(),pd.dropna()

数据连接(pd.merge)

  • pd.merge
  • 根据单个或多个键将不同DataFrame的行连接起来
  • 类似数据库的连接操作

示例代码:

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

运行结果:

   data1 key   data1 key0      8   b1      8   b2      3   a3      5   c4      4   a5      9   a6      6   b   data2 key0      9   a1      0   b2      3   d

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

示例代码:

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

运行结果:

   data1 key  data20      8   b      01      8   b      02      6   b      03      3   a      94      4   a      95      9   a      9

2. on显示指定"外键"

示例代码:

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

运行结果:

   data1 key  data20      8   b      01      8   b      02      6   b      03      3   a      94      4   a      95      9   a      9

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

示例代码:

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

运行结果:

   data1 key1  data2 key20      8    b      0    b1      8    b      0    b2      6    b      0    b3      3    a      9    a4      4    a      9    a5      9    a      9    a

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

how指定连接方式

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

示例代码:

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

运行结果:

   data1 key1  data2 key20    8.0    b    0.0    b1    8.0    b    0.0    b2    6.0    b    0.0    b3    3.0    a    9.0    a4    4.0    a    9.0    a5    9.0    a    9.0    a6    5.0    c    NaN  NaN7    NaN  NaN    3.0    d

5. "左连接"(left)

示例代码:

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

运行结果:

   data1 key1  data2 key20      8    b    0.0    b1      8    b    0.0    b2      3    a    9.0    a3      5    c    NaN  NaN4      4    a    9.0    a5      9    a    9.0    a6      6    b    0.0    b

6. "右连接"(right)

示例代码:

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

运行结果:

   data1 key1  data2 key20    8.0    b      0    b1    8.0    b      0    b2    6.0    b      0    b3    3.0    a      9    a4    4.0    a      9    a5    9.0    a      9    a6    NaN  NaN      3    d

7. 处理重复列名

suffixes,默认为_x, _y

示例代码:

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

运行结果:

   data_left key  data_right0          9   b           11          5   b           12          1   b           13          2   a           84          2   a           85          5   a           8

8. 按索引连接

left_index=True或right_index=True

示例代码:

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

运行结果:

   data1 key  data20      3   b      61      4   b      66      8   b      62      6   a      04      3   a      05      0   a      0

数据合并(pd.concat)

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

1. NumPy的concat

np.concatenate

示例代码:

import numpy as npimport pandas as pdarr1 = np.random.randint(0, 10, (3, 4))arr2 = np.random.randint(0, 10, (3, 4))print(arr1)print(arr2)print(np.concatenate([arr1, arr2]))print(np.concatenate([arr1, arr2], axis=1))

运行结果:

# print(arr1)[[3 3 0 8] [2 0 3 1] [4 8 8 2]]# print(arr2)[[6 8 7 3] [1 6 8 7] [1 4 7 1]]# print(np.concatenate([arr1, arr2])) [[3 3 0 8] [2 0 3 1] [4 8 8 2] [6 8 7 3] [1 6 8 7] [1 4 7 1]]# print(np.concatenate([arr1, arr2], axis=1)) [[3 3 0 8 6 8 7 3] [2 0 3 1 1 6 8 7] [4 8 8 2 1 4 7 1]]

2. pd.concat

  • 注意指定轴方向,默认axis=0
  • join指定合并方式,默认为outer
  • Series合并时查看行索引有无重复

1) index 没有重复的情况

示例代码:

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

运行结果:

# print(ser_obj1)0    11    82    43    94    4dtype: int64# print(ser_obj2)5    26    67    48    2dtype: int64# print(ser_obj3)9     610    211    7dtype: int64# print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))0     11     82     43     94     45     26     67     48     29     610    211    7dtype: int64# print(pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1))      0    1    20   1.0  NaN  NaN1   5.0  NaN  NaN2   3.0  NaN  NaN3   2.0  NaN  NaN4   4.0  NaN  NaN5   NaN  9.0  NaN6   NaN  8.0  NaN7   NaN  3.0  NaN8   NaN  6.0  NaN9   NaN  NaN  2.010  NaN  NaN  3.011  NaN  NaN  3.0

2) index 有重复的情况

示例代码:

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

运行结果:

# print(ser_obj1)0    01    32    73    24    5dtype: int64# print(ser_obj2)0    51    12    93    9dtype: int64# print(ser_obj3)0    81    72    9dtype: int64# print(pd.concat([ser_obj1, ser_obj2, ser_obj3]))0    01    32    73    24    50    51    12    93    90    81    72    9dtype: int64# print(pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1, join='inner')) # join='inner' 将去除NaN所在的行或列   0  1  20  0  5  81  3  1  72  7  9  9

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

示例代码:

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

运行结果:

# print(df_obj1)   A  Ba  3  3b  5  4c  8  6# print(df_obj2)   C  Da  1  9b  6  8# print(pd.concat([df_obj1, df_obj2]))     A    B    C    Da  3.0  3.0  NaN  NaNb  5.0  4.0  NaN  NaNc  8.0  6.0  NaN  NaNa  NaN  NaN  1.0  9.0b  NaN  NaN  6.0  8.0# print(pd.concat([df_obj1, df_obj2], axis=1, join='inner'))   A  B  C  Da  3  3  1  9b  5  4  6  8

数据重构

1. stack

  • 将列索引旋转为行索引,完成层级索引
  • DataFrame->Series

示例代码:

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

运行结果:

# print(df_obj)   data1  data20      7      91      7      82      8      93      4      14      1      2# print(stacked)0  data1    7   data2    91  data1    7   data2    82  data1    8   data2    93  data1    4   data2    14  data1    1   data2    2dtype: int64

2. unstack

  • 将层级索引展开
  • Series->DataFrame
  • 让操作内层索引,即level=-1

示例代码:

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

运行结果:

# print(stacked.unstack())   data1  data20      7      91      7      82      8      93      4      14      1      2# print(stacked.unstack(level=0))       0  1  2  3  4data1  7  7  8  4  1data2  9  8  9  1  2

数据转换

一、 处理重复数据

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

示例代码:

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

运行结果:

# print(df_obj)  data1  data20     a      31     a      22     a      33     a      34     b      15     b      06     b      37     b      0# print(df_obj.duplicated())0    False1    False2     True3     True4    False5    False6    False7     Truedtype: bool

2 drop_duplicates() 过滤重复行

默认判断全部列

可指定按某些列判断

示例代码:

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

运行结果:

# print(df_obj.drop_duplicates())  data1  data20     a      31     a      24     b      15     b      06     b      3# print(df_obj.drop_duplicates('data2'))  data1  data20     a      31     a      24     b      15     b      0

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

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

示例代码:

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

运行结果:

# print(ser_obj)0    11    42    83    64    85    66    67    48    79    3dtype: int64# print(ser_obj.map(lambda x : x ** 2))0     11    162    643    364    645    366    367    168    499     9dtype: int64

二、数据替换

replace根据值的内容进行替换

示例代码:

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

运行结果:

# print(ser_obj.replace(1, -100))0   -1001      42      83      64      85      66      67      48      79      3dtype: int64# print(ser_obj.replace([6, 8], -100))0      11      42   -1003   -1004   -1005   -1006   -1007      48      79      3dtype: int64# print(ser_obj.replace([4, 7], [-100, -200]))0      11   -1002      83      64      85      66      67   -1008   -2009      3dtype: int64
0