pandas 数据处理

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,1000CU*H 3个月
简介: pandas 数据处理

pandas 数据清洗

1. 去除 NaN 值

在Pandas的各类数据Series和DataFrame里字段值为NaN的为缺失数据,不代表0而是说没有赋值数据,类似于python中的None值。数据的缺失有很多原因,缺失不是错误、无效,需要对缺失的数据进行必要的技术处理,以便后续的计算、统计。

可以通过numpy 模块的 nan 得到NaN 值。

首先,可以通过isnull 和 notnull 方法查看有哪些NaN值,这两个方法返回的布尔值,指示该值是否是NaN值,结合sum 方法可以获取每列空值的数目以及总数。也可以通过 count 方法得到每列不为NaN值的数目。

dropna()

删除NaN 值 可以通过 dropna 方法,默认按行扫描(操作),会将每一行有NaN 值的那一行删除,同时默认是对原对象的副本操作,不会对原对象产生影响,也可以通过inplace 指示是否直接在原对象上操作。
示例:

import pandas as pd
import numpy as np
val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
df["e"] = np.nan
df.at["make", "e"] = 100
print(df)
print(df.dropna())
print(df)

"""
       a   b   c   d    e    print(df)
cake  10  11  12  13  NaN
make  14  15  16  17  100
fake  18  19  20  21  NaN
sake  22  23  24  25  NaN
wake  26  27  28  29  NaN
lake  30  31  32  33  NaN
take  34  35  36  37  NaN
       a   b   c   d    e    print(df.dropna())
make  14  15  16  17  100
       a   b   c   d    e    print(df)
cake  10  11  12  13  NaN
make  14  15  16  17  100
fake  18  19  20  21  NaN
sake  22  23  24  25  NaN
wake  26  27  28  29  NaN
lake  30  31  32  33  NaN
"""

dropna 方法可以选择删除

# 要删除一列或一行中全部都是nan 值的那一行或列,可以通过下面的方式 
print("del cols is all NaN\n", df.dropna(axis = 'columns', how='all'))    # how='all'  指明要这一列全部是nan值才删除,axis 案列操作
print("del rows is all NaN\n", df.dropna(axis = 'rows', how='all'))    # axis 按行操作,how 原理同上


# 同时可以添加条件删除
print(df.dropna(axis = 1, thresh = 2))    # axis=1按列操作,thresh 指示这一列或行中有两个或以上的非NaN 值的行或列被保留

通过布尔判断,也是可以实现删除 NaN 的功能。

# 使用布尔逻辑判断,下面两句代码功能一致。
print(df.e[df.e.notnull()])
print(df.e.dropna())

2. 填充NaN 值

一般情况下直接将NaN删除或许并不是最好的选择因此可以通过将NaN值进行填充。

fillna()

fillna 方法可以将df 中的nan 值按需求填充成某值

# 将NaN值用0填充
df.fillna(0,inplace = True)    # inplace 指明在原对象上直接修改

复杂的 使用向前 或 向后 填充数据,依旧使用fillna 方法,所谓向前 是指 取出现NaN值的前一列或前一行的数据来填充NaN值,向后同理

# 在df 的e 这一列上操作,默认下按行操作,向前填充数据,即取e列中最近的一个不为NaN值来填充接下去的NaN值
df["e"].fillna(method = 'ffill',inplace=True)
# 原理同上,只是取e列中最近的一个不为NaN值并且它的上一个数值是NaN值 的值来填充接下去的NaN值
df["e"].fillna(method = 'bfill',inplace=True)
# 对 gake 行操作,axis=0按行操作,取该行中最先出现的一个不为NaN值填充接下去的NaN值
df.loc["gake"].fillna(method = 'ffill',inplace=True, axis = 0)
# 原理同上,只是变成了向后取值
df.loc["gake"].fillna(method = 'bfill',inplace=True, axis = 0)
# 对整个df 正常,按列操作,取最先出现NaN值的前一列数值,用来填充接下去出现NaN值的全部列
df.fillna(method = 'ffill',inplace=True, axis = 1)

也可以通过重新赋值的赋值来填充NaN值,即将一个series 赋值给df 的某一列 来达到删除NaN值的目的。

interpolate()

利用插值函数interpolate()对列向的数据进行填值。实现插值填充数据,那么要求这列上必须得有一些数据才可以,至少2个,会对起点和终点间的NaN进行插值。
示例:

val = np.arange(10, 38).reshape(7, 4)
col = list("abcd")
idx = "cake make fake sake wake lake take".split()
df = pd.DataFrame(val, columns = col, index = idx)
df["e"] = np.nan
df.at["fake", "e"] = 100
df.at["lake", "e"] = 600
df["f"] = np.nan
df.loc["gake"] = np.nan 
df.at["gake", "c"] = 700
df["e"].interpolate(inplace=True)
df["f"].interpolate(inplace=True)
"""
       a   b    c   d    e   f
cake  10  11   12  13  NaN NaN
make  14  15   16  17  NaN NaN
fake  18  19   20  21  100 NaN
sake  22  23   24  25  NaN NaN
wake  26  27   28  29  NaN NaN
lake  30  31   32  33  600 NaN
take  34  35   36  37  NaN NaN
gake NaN NaN  700 NaN  NaN NaN    df
       a   b    c   d           e   f
cake  10  11   12  13         NaN NaN
make  14  15   16  17         NaN NaN
fake  18  19   20  21  100.000000 NaN
sake  22  23   24  25  266.666667 NaN
wake  26  27   28  29  433.333333 NaN
lake  30  31   32  33  600.000000 NaN
take  34  35   36  37  600.000000 NaN
gake NaN NaN  700 NaN  600.000000 NaN    df.interpolate()
"""

可以看出,当待填充的列或行符合条件时,会从最近的那个非NaN值开始将之后的位置全部填充,填充的数值为列上保留数据的最大值最小值之间的浮点数值。

3. 删除重复数据

对于数据源中的重复数据,一般来讲没有什么意义,所以一般情况下都会进行删除操作。

duplicated()

duplicated 方法可以返回重复数据的分布情况,以布尔值显示。

col = ["apple", "pearl", "watermelon"] * 4
pri = [2.50, 3.00, 2.75] * 4
df = pd.DataFrame({
   "fruit": col, "price" : pri})
df.duplicated()
# drop_duplicates 方法用于删除
df.drop_duplicates()
df.drop_duplicated(["page"], keep="first", inplace=True)

drop_duplicated()

删除重复值,可以指定inplace 是否在原对象上直接操作,keep= last first false 等 默认first保留第一次出现的重复数据,last同时保留最后一次出现的重复数据,false 不保留

使用如上。

4. 数据匹配替换

简单数据删除填充有时并不能满足需求,因此需要数据进行匹配替换满足更进一步的需求。

map()

map函数可以将某列数据映射成其它数据

oSeries = pd.Series(["a", "b", "c"], index = [2,3,1])
iSeries = pd.Series([100,200, 300], index = ["c","b","a"])
oSeries.map(iSeries)
"""
2    a
3    b
1    c
dtype: object    oSeries
c    100
b    200
a    300
dtype: int64    iSeries
2    300
3    200
1    100
dtype: int64    oSeries.map(iSeries)
"""
# 将oSeries 的value 替换成了 iSeries 的value

map 一般对index 和 series 等使用。

replace()

将数据替换成其他数据,可以一对一的替换也可一堆多的替换数据。

# 对series 而言,简单的一对一替换
ss = pd.Series(["a", "b", "c"], index = [2,3,1])
ss.replace("b", "hello", inplace = True)
# 同样可以多对多替换
ss.replace(["c", "a"], ["hello", "world"], inplace = True)
# 字典形式传参也可以,key是待替换的值,value是替换的值
ss.replace({
   "c":"hello", "a" : "world"}, inplace = True)


# 对dataframe 而言,使用replace 稍有不同
idx = [1,3,2,4]
val = {
   'name' : "hello the cruel world".split(),
       'growth' : [100, 125, 150, 200]}
df = pd.DataFrame(val, idx)
# 第一个以字典形式确定要替换被的元素,key为元素所在行,value为待替换数值,第二个参数是替换成的值
df.replace({
   "name" : "the"}, "THE", inplace = True)

5. apply() 方法使用

replace、dropna、fillna函数要么针对NaN的某行或某列或某个,这些函数的作用有限,本章介绍的apply等函数可以针对整个Series或DataFrame的各个值进行相应的数据的处理

对series 使用apply

# 对series 使用apply ,会将series 中的每个元素执行操作
s = pd.Series(np.arange(2,6))
s.apply(lambda x : 2 * x)

对dataframe 使用apply

# 对df 使用apply,都是按行或按列操作,不能保证对每一个元素进行操作
df = pd.DataFrame(val, index=idx, columns=col)
# 按行操作,对数据求和
print(type(df.apply(lambda col: col.sum(), axis='rows')))
# 按列操作,对数据求和
print(df.apply(lambda row: row.sum(), axis='columns'))
# df["hello x the"] = df.apply(lambda row: row.hello * row.the, axis=1)

df 中的applymap()

df 中使用applymap 可以对df 中的每一个元素进行操作

val = np.arange(10, 60).reshape(10, 5)
idx = np.arange(10, 20)
col = list('abcde')
df = pd.DataFrame(val, index = idx, columns = col)
# df 中的每一个元素都会被加3
print(df.applymap(lambda x : x + 3))

pandas 数据拼接

1. concat() 拼接方法

对series 操作

s1 = pd.Series(np.arange(2,6))
s2 = pd.Series(np.arange(8,12))
# 后一个series 接在前一个series后面
ss = pd.concat([s1, s2])

对dataframe 操作

# 两个DataFrame的拼接 1). label和columns均相同的情况下:
col = "hello the cruel world".split()
idx = ["a", "b", "c", "d"]
val1 = np.arange(16).reshape(4, 4)
val2 = np.arange(20, 36).reshape(4, 4)
df1 = pd.DataFrame(val1, index = idx, columns = col)
df2 = pd.DataFrame(val2, index = idx, columns = col)
# 在列标 相同的情况下,就是后一个df 接在前一个df 后面
df12 = pd.concat([df1, df2])

当然,列标和行标不一定是对应的,这个时候两DataFrame未匹配上的label或columns下的值为NaN

concat 函数 同样的可以指定是按行操作还是按列操作。

指定拼接的轴,默认是列方向的拼接数据,可以指定concat 的形参axis为行上的拼接数据。

2. concat 的内外连接

concat 的内外连接,就是 join 参数的指定,为 inner 时为内连接,为outer 时外连接。

col1 = "hello the cruel world".split()
col2 = "hello the nice world".split()
idx1 = ["a", "b", "c", "d"]
idx2 = ["a", "b", "d", "e"]
val1 = np.arange(16).reshape(4, 4)
val2 = np.arange(20, 36).reshape(4, 4)
df1 = pd.DataFrame(val1, index = idx1, columns = col1)#
df2 = pd.DataFrame(val2, index = idx2, columns = col2)
# "***outer join"
pd.concat([df1, df2], join = "outer")
# "***inner join"
pd.concat([df1, df2], join = "inner")
# concat 的内外连接 实际上就是对两个df 求交集还是并集的选择
# 外连接就是并集,内连接就是交集

3. merge() 方法

merge函数可以真正实现数据库的内外连接,且外连接还可以有左右连接的特性。

补充:

内连接,对两张有关联的表进行内连接操作,结果表会是两张表的交集,例如A表和B表,如果是A 内连接(inner join)B表,结果表是以A为基准,在B中找寻A匹配的行,不匹配则舍弃,B内连接A同理。
外连接,分左外连接,右外连接,全连接,左外连接是左表上的所有行匹配右表,正常能匹配上的取B表的值,不能的取空值,右外连接同理,全连接则是取左并上右表的的所有行,没能匹配上的用空值填充。

merge 默认是内连接

# 默认情况下,merge函数是内连接
print(course.merge(choose))
# 变换两张表的位置,得到的结果并不一样
print(choose.merge(course))

merge可以进行左外连接,右外连接,全连接。

# 通过指定how 参数可以进行全连接,course表并上choose表得出结果
print(course.merge(choose, how = "outer"))
# 同理,choose表并上course表得出结果
print(choose.merge(course, how = "outer"))

# merge进行左右外连接
# course表左外连接choose表,结果保留course 的全部行及列,和choose表进行匹配,不匹配以空值替代
print course.merge(choose, how = "left")
# course 表右外连接choose表,结果保留choose表的全部行列,和course表进行匹配,同时course表的数据会显示在choose表前
print course.merge(choose, how = "right")
# choose表左外连接course,和course表右外连接choose表结果一致,但choose表的数据显示在前
print choose.merge(course, how = "left")
# 和course 左外连接 choose结果一样,但每列数据的排列会有区别,因为结果表会先显示左表的结果
print choose.merge(course, how = "right")

pandas 数据分组

1. groupby 方法

DataFrame数据对象经groupby()之后有ngroups和groups等属性,其本质是DataFrame类的子类DataFrameGroupBy的实例对象。ngroups反应的是分组的个数,而groups类似dict结构,key是分组的index或label,value则为index或label所对应的分组数据。size函数则是可以返回所有分组的字节大小。count函数可以统计分组后各列数据项个数。get_group函数可以返回指定组的数据信息。而discribe函数可以返回分组后的数据的统计数据。

简单的按单列分组

# 按单列进行分组
dg =  df0.groupby("fruit")
# 打印查看按fruit分组后的每组组名,及详细信息
for n, g in dg:
    print "group_name:", n, "\n|",g,"|" 
# 查看组名和 每组的数据信息
for n,_ in dg:
    print "group_name:", n, "\n|",dg.get_group(n),"|" 
# 查看分组后的统计数据
print dg.describe()

也支持多列分组

dg1 =  df0.groupby(["fruit", "supplier"])
for n, g in dg1:
    print "multiGroup on:", n, "\n|",g ,"|"

2. aggregate 聚合

在使用groupby 分组完成后,借助aggregate函数可以 经过分组后 每组进行操作。

agg的形参是一个函数会对分组后每列都应用这个函数。

# 分组后对每组数据求平均值
print dg1.agg(np.mean)

也可以应用多个函数

# 以列表的形式传入参数即可,会对每组都执行全部的聚合函数
print dg1.agg([np.mean, np.std, np.min, np.sum])

可以对每列数组进行不同的聚合操作

# 传入字典,key为列名,value为要执行的聚合函数
print dg1.agg({
   "price" : np.mean, "supplier" : np.max})

3. transform() 方法

可以作用于groupby之后的每个组的所有数据,之前的aggregate函数只能用于分组后组的每列数据。

import pandas as pd
import numpy as np
idx = [101,101,101,102,102,102,103,103,103]
idx += [101,102,103] * 3
name = ["apple","pearl","orange", "apple","pearl","orange","apple","pearl","orange"]
name += ["apple"] * 3 + ["pearl"] * 3 + ["orange"] * 3
price = [4.1,5.3,6.3,4.20,5.4,6.0,4.5,5.5,6.8]
price += [4] * 3 + [5] * 3 + [6] * 3
df0 = pd.DataFrame({
    "fruit": name, "price" : price, "supplier" :idx})
dg1 =  df0.groupby(["fruit"])
def f1(x):
    return x + 1
def f2(x):
    return x + 100
# 选择某一列,调用transform方法,对每个数据都执行f1函数
print dg1["price"].transform(f1)[:3]
print dg1["supplier"].transform(f2)[:3]
# 直接调用对每个元素都执行f2 函数
print dg1.transform(f2)[:3]

# [:3] 是只打印前三个元素的意思

pandas 时间序列

时间序列数据在金融、经济、神经科学、物理学里都是一种重要的结构化的数据表现形式。
pandas 最基本的时间序列类型就是以时间戳(TimeStamp)为 index 元素的 Series 类型。Python和Pandas里提供大量的内建工具、模块可以用来创建时间序列类型的数据。

1. datetime 模块

Python的datetime标准模块下的

date子类可以创建日期时间序列的数据

time子类可创建小时分时间数据

datetime子类则可以描述日期小时分数据

import datetime
# 日期小时分秒 日期数据
cur = datetime.datetime(2018,12,30, 15,30,59)
print(cur,type(cur))
# 获得日类类型的时间数据
d = datetime.date(2018,12,30)
print(d)
# 获得小时分数据
t = datetime.time(12, 30, 5)
print(t)

datetime的timedelta模块给出时间间隔(差)

借助timedelta 可以定义时间时间间隔

# 设置一个日期
cur0 = datetime.datetime(2018,12,30, 15,30,59)
# 获取 从 cur0 加上一天的时间间隔
cur1 = cur0 + datetime.timedelta(days = 1)
# cur0 加上 10分钟的时间间隔
cur2 = cur0 + datetime.timedelta(minutes = 10)
# cur0 加上 29分钟 1秒的时间间隔
cur3 = cur0 + datetime.timedelta(minutes = 29,seconds = 1)

用datetime数据创建time series时间序列数据。意思就是用datetime创建的时间作为index。.

from datetime import datetime, timedelta
import numpy as np
import pandas as pd
b = datetime(2018,12,16, 17,30,55)
vi = np.random.randn(60)
ind = []
for x in range(60):
    bi = b + timedelta(minutes = x)
    ind.append(bi)
# series 的index 为 一串时间数据
ts = pd.Series(vi, index = ind)
# 显示前5条数据
print ts[:5]
目录
相关文章
|
1月前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
232 0
|
1月前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
375 0
|
3月前
|
存储 数据采集 数据处理
Pandas与NumPy:Python数据处理的双剑合璧
Pandas与NumPy是Python数据科学的核心工具。NumPy以高效的多维数组支持数值计算,适用于大规模矩阵运算;Pandas则提供灵活的DataFrame结构,擅长处理表格型数据与缺失值。二者在性能与功能上各具优势,协同构建现代数据分析的技术基石。
351 0
|
5月前
|
运维 数据挖掘 数据处理
Pandas时间数据处理:从基础到进阶的实战指南
Pandas时间数据处理涵盖了从基础到高级的全面功能。其核心由Timestamp、DatetimeIndex、Period和Timedelta四个类构建,支持精准的时间点与区间操作。内容包括时间数据生成(字符串解析与序列生成)、时间索引与切片、高级运算(偏移重采样与窗口计算)、时区处理、周期性数据分析及实战案例(如智能电表数据)。此外,还涉及性能优化技巧和未来展望,帮助用户高效处理时间序列数据并应用于预测分析等场景。
268 1
|
5月前
|
传感器 安全 数据处理
Pandas时间数据处理:从基础到进阶的实战指南
本文深入讲解Pandas时间数据处理技巧,从时间对象转换到高性能计算全面覆盖。通过真实案例拆解,掌握Timestamp与Period的核心概念、时间序列生成、重采样方法及窗口函数应用。同时剖析时区处理、性能优化策略及常见陷阱解决方案,并展望Pandas 2.0的时间处理新特性。内容强调“时间索引优先”原则,助你高效分析股票K线、用户行为等时间序列数据。
169 0
|
9月前
|
数据可视化 数据挖掘 数据处理
Pandas高级数据处理:交互式数据探索
Pandas 是数据分析中常用的数据处理库,提供了强大的数据结构和操作功能。本文从基础到高级,逐步介绍 Pandas 中交互式数据探索的常见问题及解决方案,涵盖数据读取、检查、清洗、预处理、聚合分组和可视化等内容。通过实例代码,帮助用户解决文件路径错误、编码问题、数据类型不一致、缺失值处理等挑战,提升数据分析效率。
223 32
|
9月前
|
数据采集 数据可视化 数据处理
Pandas高级数据处理:数据仪表板制作
《Pandas高级数据处理:数据仪表板制作》涵盖数据清洗、聚合、时间序列处理等技巧,解决常见错误如KeyError和内存溢出。通过多源数据整合、动态数据透视及可视化准备,结合性能优化与最佳实践,助你构建响应快速、数据精准的商业级数据仪表板。适合希望提升数据分析能力的开发者。
260 31
|
9月前
|
存储 安全 数据处理
Pandas高级数据处理:数据安全与隐私保护
在数据驱动的时代,数据安全和隐私保护至关重要。本文探讨了使用Pandas进行数据分析时如何确保数据的安全性和隐私性,涵盖法律法规要求、用户信任和商业价值等方面。通过加密、脱敏、访问控制和日志审计等技术手段,结合常见问题及解决方案,帮助读者在实际项目中有效保护数据。
317 29
|
9月前
|
缓存 数据可视化 BI
Pandas高级数据处理:数据仪表板制作
在数据分析中,面对庞大、多维度的数据集(如销售记录、用户行为日志),直接查看原始数据难以快速抓住重点。传统展示方式(如Excel表格)缺乏交互性和动态性,影响决策效率。为此,我们利用Python的Pandas库构建数据仪表板,具备数据聚合筛选、可视化图表生成和性能优化功能,帮助业务人员直观分析不同品类商品销量分布、省份销售额排名及日均订单量变化趋势,提升数据洞察力与决策效率。
214 12
|
9月前
|
存储 安全 数据处理
Pandas高级数据处理:数据加密与解密
本文介绍如何使用Pandas结合加密库(如`cryptography`)实现数据加密与解密,确保敏感信息的安全。涵盖对称和非对称加密算法、常见问题及解决方案,包括密钥管理、性能优化、字符编码和数据完整性验证。通过示例代码展示具体操作,并提供常见报错的解决方法。
183 24