【无痛学Python】Pandas数据载入与预处理,看这一篇就够了!

【Python数据分析】Pandas数据载入与预处理,看这一篇就够了!

对于数据分析而言,数据大部分来源于外部数据,例如CSV文件、Excel文件以及数据库文件等等。

我们要把各种格式的数据转换成Pandas可处理的Series和DataFrame数据格式,进行完数据分析与处理之后再重新存储到外部文件中,这就是Pandas的数据载入与预处理

数据载入

其实对于读/写文件和存储文件来说,不同类型文件的函数格式都差不多,遵循以下格式:

读/写文件:read_xxx

存储文件:to_xxx

区别主要还是在参数类型的不同上。

1.读/写文本文件

文本文件是一种由若干行字符构成的文件,同时它也是一种按照顺序来进行书写的文件。

文本文件分为普通的文本文件CSV文件

CSV文件是一种使用逗号分隔的文件格式,但因为有时候又不一定是逗号,所以也被称为 字符分隔文件

文本文件都以纯文本形式保存数据。

  • 使用read_table()来读取文本文件

  • 使用read_csv()来读取CSV文件

    它们有如下的参数:

    参数 说明
    filepath 接受string,代表文件路径
    sep 接受string,代表分隔符。table默认为[Tab],csv默认为”,“ 。注意:如果分隔符指定错误,就会导致数据连成一片
    header 接受int或sequence,将某行数据作为列名,默认为infer,即自动识别
    names 接受array,表示列名,默认为None
    index_col 接受int、sequence或False,表示索引列的位置,默认为None
    dtype 接受dict,代表写入的数据类型(列名为key,数据格式为values),默认为None
    engine 接受c或者python,代表你要使用编程语言引擎,默认为c
    nrows 接受int,表示读取前n行,默认为None
    df1 = pd.read_csv('xxx文件路径名')
    df2 = pd.read_table('xxx文件路径名',sep = ',')
    df3 = pd.read_csv('xxx文件路径名',names = ['a','b','c'])
    

2.文本文件的存储

使用to_table或者to_csv进行存储。

读/写Excel文件

1.Excel文件的读取

Pandas允许读取xls和xlsx两种Excel文件。

使用read_excel

部分参数与文本文件的相同,以下只介绍多出来的部分(其实也只有一个)。

参数 说明
sheetname 接受string,int,表示Excel表内数据的分表位置,默认为0

2.Excel文件的存储

使用to_excel

常用参数也基本一致,主要区别在于由于Excel是表格形式,没有sep作为分隔符,并且多出了sheetname来指定存储的Excel Sheet的名称,默认为sheet1

读/写JSON数据

JSON作为一种轻量级的数据交换格式,使用大括号来区分表示并存储。

1.JSON数据的读取

使用read_json

由于有时候会出现顺序错乱的问题,我们要使用sort_index来对行索引进行一下排序。

2.JSON数据的存储

使用to_json

读取数据库文件

数据库是数据分析中很重要的一个部分。那么对它的读取也就显得格外值得重视。

对于数据库文件的读取,我们要注意,首先要进行数据库的连接connect(),然后是读取read_sql,最后还要进行关闭close()

1.读取MySQL数据

import pandas as pd
import MySQLdb
conn = MySQLdb.connect(host = host,port = port,user = username,passwd = password,db = db_name)
df = pd.read_sql("select * from table_name",con = conn)
conn,close()

2.读取SQL Server数据

import pandas as pd
import pymssql
conn = pymssql.connect(host = host,port = port,user = username,passwd = password,db = db_name)
df = pd.read_sql("select * from table_name",con = conn)
conn,close()

合并数据

如果有不同的数据来源,就要进行数据的合并。

1.merge数据合并

merge函数通过一个或多个键将两个DataFrame按行合并起来处理。它与SQL中的join的用法类似。

格式就没必要写了,直接介绍参数。

参数 说明
left 参与合并的左侧DataFrame
right 参与合并的右侧DataFrame
how 连接方法:inner(默认),left,right,outer(这里需要自行去了解下几个合并方法的概念)
on 用于连接的列名
left_on 左侧DataFrame中用于连接键的列
right_on 右侧DataFrame中用于连接键的列
left_index 左侧行索引作为连接键
right_index 右侧行索引作为连接键
sort 合并后会对数据进行排序,默认为Ture
suffixes 修改重复名
# merge合并数据
price = pd.DataFrame({'fruit':['apple','orange','pear','orange'],'price':[8,7,9,11]})
# print(price)
amount = pd.DataFrame({'fruit':['apple','orange','pear'],'amout':[5,11,8],'price':[879]})
# print(amount)
print(pd.merge(price,amount))
    fruit  price  amout
0   apple      8      5
1  orange      7     11
2    pear      9      8
3  orange     11     11

由于两个DataFrame都由fruit列,所以默认会按照这个列来进行合并,并且根据默认的连接方法inner进行合并。

如果不想要根据默认的列来进行合并,可以进行指定

# merge合并数据
price = pd.DataFrame({'fruit':['apple','orange','pear'],'price':[8,7,9]})
# print(price)
amount = pd.DataFrame({'fruit':['apple','orange','pear'],'amout':[5,11,8],'price':[8,7,9]})
# print(amount)
print(pd.merge(price,amount,left_on='price',right_on='price'))

当你使用这样的代码进行输出你会发现有以下问题:

  fruit_x  price fruit_y  amout
0   apple      8   apple      5
1  orange      7  orange     11
2    pear      9    pear      8

这里的fruit_xfruit_y实际上就是重复的列,系统默认用_x 和 _y来区分,我们要消除的话,就可以使用suffixes参数来进行消除重复列名。

# merge合并数据
price = pd.DataFrame({'fruit':['apple','orange','pear'],'price':[8,7,9]})
# print(price)
amount = pd.DataFrame({'fruit':['apple','orange','pear'],'amout':[5,11,8],'price':[8,7,9]})
# print(amount)
print(pd.merge(price,amount,left_on='price',right_on='price',suffixes=('_left','_right')))
  fruit_left  price fruit_right  amout
0      apple      8       apple      5
1     orange      7      orange     11
2       pear      9        pear      8

2.concat数据连接

如果两个DataFrame之间没有连接键,那么就无法使用merge方法。

# merge合并数据
price = pd.DataFrame({'fruit':['apple','orange','pear','orange'],'price':[8,7,9,11]})
amount = pd.DataFrame({'name':['apple','orange','pear'],'amout':[5,11,8]}) # 这样就会报错
print(pd.merge(price,amount))

那么我们就可以用concat来进行连接。我们其实可以这样理解,merge就是合并,那么合并就必须得有相同的部分,也就是连接键;而concat就是连接,连接不一定需要相同的部分。

默认情况下会按照行的方向进行数据的堆叠,axis=1时就是列。

# concat连接数据
s1 = pd.Series([0,1],index = ['a','b'])
s2 = pd.Series([2,3,4],index = ['a','d','e'])
s3 = pd.Series([5,6],index = ['f','g'])
print(pd.concat([s1,s2,s3]))
# 只显示DataFrame的示例
data1 = pd.DataFrame(np.arange(6).reshape(2,3),columns=list('abc'))
print(data1)
data2 = pd.DataFrame(np.arange(20,26).reshape(2,3),columns=list('ayz'))
print(data2)
data = pd.concat([data1,data2],axis=0)
print(data)
   a  b  c
0  0  1  2
1  3  4  5
    a   y   z
0  20  21  22
1  23  24  25
    a    b    c     y     z
0   0  1.0  2.0   NaN   NaN
1   3  4.0  5.0   NaN   NaN
0  20  NaN  NaN  21.0  22.0
1  23  NaN  NaN  24.0  25.0

如果axis=1,会有以下
   a  b  c   a   y   z
0  0  1  2  20  21  22
1  3  4  5  23  24  25

可以看出,concat默认为外连接,那么我们也可以指定join使用别的连接方式。

3.combine_first合并数据

如果有重复的索引,就使用combine_first

data0 = data1.combine_first(data2)
print(data0)

注意,如果重复索引的数据不一样,会默认使用第一个DataFrame中的数据。

   a  b  c   a   y   z
0  0  1  2  20  21  22
1  3  4  5  23  24  25
   a  b  c   y   z
0  0  1  2  21  22
1  3  4  5  24  25

数据清洗

数据一般时不完整、有噪声和不一致的。数据清洗包括填充缺失的数据值、光滑噪声等等。

确实,前面的操作我们发现虽然进行了数据的分析,但是总感觉有些看起来不够顺眼,而数据清洗就是让数据看起来更顺眼的。

检测与处理缺失值

1.缺失值的处理

  • 使用isnull检测缺失值,通常是返回布尔值,如果是缺失值则返回True,否则返回False
  • 使用isnull().sum()统计缺失值,也可以使用info()来查看DataFrame的缺失值
  • 使用dropna删除具有缺失值的行或列,其中参数:axis默认为0;how如果是’any’(默认),说明只要有缺失值就删除,如果是’all’,说明如果该行或者列全是缺失值在进行删除;thresh用于说明阙值;inplace说明是否对原数据进行返回。
  • 使用fillna填充缺失值,往往这个方法更常用,毕竟直接删除数据不太好。填充值一般是平均数、中位数或者众数之类较为稳定的数据,当然也可以指定一个常数,**更甚至可以用字典形式来实现不同列填充不同值。**inplace参数可以指定是返回新对象还是直接对原数据进行修改。

2.检测与处理重复值

如果有重复值,我们只需要保留一份即可,我们使用duplicates可以进行判断是否有重复,使用drop_duplicates进行重复值的删除。

# 检测与处理重复值

data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'David', 'Alice'],
    'age': [25, 30, 35, 25, 40, 25],
    'salary': [5000, 7000, 8000, 5000, 9000, 6000]
}

df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)

# 检测重复值(所有列)
duplicates = df.duplicated()
print("\n检测重复值(所有列):")
print(duplicates)

# 检测重复值(特定列 'name' 和 'age')
duplicates_subset = df.duplicated(subset=['name', 'age'])
print("\n检测重复值(特定列 'name' 和 'age'):")
print(duplicates_subset)

# 删除所有列的重复值
df_no_duplicates = df.drop_duplicates()
print("\n删除所有列的重复值后的DataFrame:")
print(df_no_duplicates)

# 删除特定列的重复值
df_no_duplicates_subset = df.drop_duplicates(subset=['name', 'age'])
print("\n删除特定列 'name' 和 'age' 的重复值后的DataFrame:")
print(df_no_duplicates_subset)
原始DataFrame:
      name  age  salary
0    Alice   25    5000
1      Bob   30    7000
2  Charlie   35    8000
3    Alice   25    5000
4    David   40    9000
5    Alice   25    6000

检测重复值(所有列):
0    False
1    False
2    False
3     True
4    False
5    False
dtype: bool

检测重复值(特定列 'name''age':
0    False
1    False
2    False
3     True
4    False
5     True
dtype: bool

删除所有列的重复值后的DataFrame:
      name  age  salary
0    Alice   25    5000
1      Bob   30    7000
2  Charlie   35    8000
4    David   40    9000
5    Alice   25    6000

删除特定列 'name''age' 的重复值后的DataFrame:
      name  age  salary
0    Alice   25    5000
1      Bob   30    7000
2  Charlie   35    8000
4    David   40    9000

检测与处理异常值

异常值指的是数据中存在的个别数值明显偏离其余数据的值,异常值会严重干扰数据分析的结果。一般在庞大数据中异常值的发现可以通过图形来进行检测,那样更明显。

这里介绍三种方法

1.散点图方法

最显著的方法,看图说话。

2.箱线图方法

箱线图使用数据中五个统计量(最小值、下四分位数Q1、中位数Q2、上四分位数Q3、最大值)来描述数据。

它可以粗略看出数据的对称性和分散程度等信息。

它如何检测异常值呢?这里有个公式:有min = Q1 - 1.5(Q3-Q1)max = Q3 + 1.5(Q3-Q1),那么小于min或者大于max的值被称为异常值。

3.使用三倍标准差法则

异常值被定义为一组测定值中与平均值的偏差超过三倍标准差的值。(因为在正态分布中,这样的值出现的概率小于0.003)

数据转换

1.数据值替换

使用replace进行数据值的替换。

# 数据转换
data = {
    'name': ['Alice', 'Bob', 'Charlie', 'Alice', 'David', '路人甲'],
    'age': [25, 30, 35, 25, 40, 25],
    'salary': [5000, 7000, 8000, 5000, 9000, 6000]
}

df = pd.DataFrame(data)
df = df.replace(['路人甲'],['李四'])
print(df)
      name  age  salary
0    Alice   25    5000
1      Bob   30    7000
2  Charlie   35    8000
3    Alice   25    5000
4    David   40    9000
5       李四   25    6000

也可以使用字典形式。

df = df.replace({'路人甲':'李四'})

如果要多值替换,使用逗号分隔就行。

2.使用函数或者映射进行数据转换

说白了就是自定义数据转换规则,使用map方法进行映射就行,不再赘述。

数据标准化

数据都得有个标准,或者说是量纲,为了消除量纲差异之间的影响,应该实现数据标准化。

离差标准化数据

使用这么一个公式:

x1 = (x - min) / (max -min)

写成函数就是:

df['age_minmax'] = (df['age'] - age_min) / (age_max - age_min)

标准差标准化数据

使用这么一个公式:

x1 = (x - mean) / std

写成函数就是:

df['age_zscore'] = (df['age'] - age_mean) / age_std

mean是平均值,std是标准差

标准化数据会不会影响数据精确性?

肯定会有人问:这样做岂不是改变了原数据的值吗?那不会影响到数据精确性吗?

数据标准化确实会改变数据的原始值,但其目的是为了更好地进行数据分析和建模。标准化不会改变数据的内在信息和结构,而是通过缩放或转换数据使其更适合特定的分析方法。

数据变换与数据离散化

数据分析的预处理除了数据清洗、数据合并和标准化之外,还有类别型数据变换和连续性数据的离散化。

类别型数据的哑变量处理

Python不能直接处理非数值型的变量,需要对这些变量进行转换。

哑变量(又称为虚拟变量),是用来反映质的属性的一个人工变量。通常取值True或者False。

我们先来看一个例子来更好理解。

# 类别型数据的转换
df = pd.DataFrame([
    ['green','M',120],
    ['blue','XL',150],
    ['red','XXL',200]
])
df.columns = ['color','size','prize']
print(df)
df1 = pd.get_dummies(df)
print(df1)
   color size  prize
0  green    M    120
1   blue   XL    150
2    red  XXL    200
   prize  color_blue  color_green  color_red  size_M  size_XL  size_XXL
0    120       False         True      False    True    False     False
1    150        True        False      False   False     True     False
2    200       False        False       True   False    False      True

可以看到,哑变量的使用使得那些不是数值类型的变量被拆分开来,通过把它们的数值名变成根据实际数据来进行分类,通过“是或者否”来进行赋值。这样很巧妙,把原先不是数值的类型,转变成了布尔值,从而更好地进行数据处理。

如果取值有m个,那么经过哑变量处理后就变成了2^m个特征,毕竟是只有True或者False两种情况。

连续型变量的离散化

通常数据都是连续性的,那样看起来不够清晰地知道它们之间的区别。我们使用离散化,将其分段,能够更明确它们的区别。

1.等宽法

使用cut方法,参数如下:

参数 说明
x 待离散化的数据
bins 表示离散化后的区间 后者是类别数目
right 代表右侧是否为闭区间,默认是True
labels 表示离散化后各个类别的名称
retbins 代表是否返回区间标签,默认不返回
precision 显示标签的精度,默认为3

2.等频法

等宽法可能会有类分布不均匀的问题,我们修改cut的用法就能实现等频。指定一个方法(0,1+0,1/k,1.0/k)

3.聚类分析法

都说物以类聚,我们可以使用聚类分析法来指定聚类的标准,为合并到同一个簇的连续性数据做同一个标记,进行数据的区分。

你可能感兴趣的:(Python,python,pandas,数据库)