Python模块-pandas

2023-11-15

数据分析虽说很多时候需要对业务和数据的理解,但其实大部分时候对数据的操作是相似(即使使用不同的工具,如Excel、Python、R等),像是数据清洗、表格结构修改、字段切分、分组计算等等。下面是使用Python中的Pandas包对数据分析常用操作的笔记。

数据读取

pandas读取文件后的数据集是一个DataFrame对象,该对象的每个列是一个Series对象

# pandas可读取很多文件格式
# 但一般读取数据的文件格式为:csv 和 excel
import pandas as pd
df = pd.read_csv("iris.csv",  
                 sep=',',
                 names=["A","B","C","D"],
                 nrows=2,  # 只要前两行的数据
                 encoding='utf-8'
                )
df = pd.read_excel("iris.xlsx",
                   sheetname='XXXX',
                   header=0,  # 指定第一行为表头
                   index_col=0,  # 指定第一列为索引
                   usecols = [0, 2]  # 只要第一和三列的数据
                  )
# 数据库读取
import pymysql # MySQL
import pymssql # SQLserver

conn = pymssql.connect(host='XXX.XX.XX.XX', user='username', password='123', database='DB')
OS = pd.read_sql("SELECT * FROM [KF_SZ].[dbo].[OSdepartrelation]",conn)
conn.close()

数据探索

# 查看数据量和特征量
df.shape
>>> (68630, 14)

# 查看数据集的头5行
df.head()

# 查看数据集的尾5行
df.tail()

# 查看行名
df.index
>>> RangeIndex(start=0, stop=68630, step=1)

# 查看列名
df.columns
>>> Index(['行号', '仓库', '货号', '条码', '商品名称'], dtype='object')

# 几乎用不上吧
df.values 

# 查看数据格式
df.dtypes
>>> 行号        int64
    仓库       object
    货号        int64
    条码       object

# 计数:每个特征(列)的非空数量
df.count()
>>> 商品名称    68630
    规格       6340
    单位      67719
    库存数量    68630

# 计数:对单个列(Series)的频数统计
df['仓库'].value_counts()
>>> 公司总部总仓库       2016
    佛山南海万科店        938
    深圳宝安兴业店        928
    深圳宝安百年店        907

# 返回唯一值的数组
df['区域'].unique()
>>> array(['深圳', '东莞', '广州', '佛山', '江门', '成都', '四川'], dtype=object)    

# 统计描述:可以对整个数据集(DataFrame),也可以对单个列(Series)
df.describe()
df['库存数量'].describe()
>>> count    68630.000000
    mean        19.545230
    std        248.819321
    min      -1600.000000
    25%          2.000000
    50%          5.000000
    75%         14.000000
    max      38080.000000
    Name: 库存数量, dtype: float64
                   
# 小技巧
df.describe().astype(np.int64).T

数据清洗

数据清洗

# 单列字段清洗-去空格
df['商品名称'] = df['商品名称'].map(lambda s : s.strip())
df['A']=df['A'].map(str.strip)   # 去除两边空格
df['A']=df['A'].map(str.lstrip)  # 去除左边空格
df['A']=df['A'].map(str.rstrip)  # 去除右边空格
df['A']=df['A'].map(str.upper)   # 转大写
df['A']=df['A'].map(str.lower)   # 转小写
df['A']=df['A'].map(str.title)   # 首字母大写

# 字段切分,并创建新特征
df.loc[:,"区域"] = df['仓库'].map(lambda s:s[0:2])

类型转换

# 转换某特征(列)的数据格式
df['行号'] = df['行号'].astype(float)  

# 转化时间格式
df['time']=pd.to_datetime(df['time'])

缺失值

  • 缺失值查看
# 缺失值判断(在原数据对象以T/F替换)
df.isnull()
df.notnull()
df['A'].isnull()
  • 缺失值统计
# 缺失值计数方法
# 方法一
df['A'].isnull().value_counts()
>>> True     68629
    False        1
    Name: A, dtype: int64
# 方法二
df['A'].isnull().sum()
>>> 68629
df.isnull().sum()
>>> 仓库          0
    货号          0
    条码          2
    规格      62290
  • 缺失值删除
# 默认axi=0,how='any': 按行,任意一行有NaN就整列丢弃
df.dropna()
df.dropna(axis=1)

# 一行中全部为NaN的,才丢弃
df.driopna(how='all')

# 保留至少3个非空值的行:一行中有3个值是非空的就保留
df.dropna(thresh=3)
  • 缺失值填充
# 整个数据集填充
df.fillna(0)

# 有针对性的填充
df.fillna({'性别':'男', '年龄':30})

重复值

# 返回布尔向量、矩阵
df['A'].duplicated()
df.duplicated()
# 整个实例一模一样才删除,默认保留第一行
df.drop_duplicates()

# 保留k1列中的唯一值的行,默认保留第一行
df.drop_duplicates(subset=["k1"])

# 保留 k1和k2 组合的唯一值的行,take_last=True 保留最后一行
df.drop_duplicates(subset=["k1","k2"], take_last=True)

值替换

# 一对一替换
# 将df的A列中 -999 全部替换成空值
df["A"].replace(-999, np.nan)

# 多对一替换
# -999和1000 均替换成空值
obj.replace([-999,1000],  np.nan)

# 多对 一对一替换
# -999替换成空值,1000替换成0
obj.replace([-999,1000],  [np.nan, 0])
# 同上,写法不同,更清晰
obj.replace({-999:np.nan, 1000:0})
# 有趣的写法
dataset_raw.loc[dataset_raw['workclass'] == 'Without-pay', 'workclass'] = 'Not Working'

修改表结构

一般数据分析需要修改表结构都是在列上动手脚,注意操作有以下几种

新增列

# 方式一
df['test'] = 0

# 方式二
df.loc[:,"区域"] = df['仓库'].map(lambda s:s[0:2])

# 方式三
df.loc[:,"is_bonus"]=1
df.loc[df['remarks']=='无奖金', 'is_bonus'] = 0

# 方式四
# 需求:创建一个新变量test2 
# 1.petal_length>2 and petal_width>0.3 = 1 
# 2.sepeal_length>6 and sepal_width>3 = 2 3.其他 = 0
df.loc[(df['petal_length']>2)&(df['petal_width']>0.3), 'test2'] = 1
df.loc[(df['sepal_length']>6)&(df['sepal_width']>3), 'test2'] = 2

删除列

# 丢弃指定的特征(列)
df.drop(['行号','条码'],
        axis=1,
        inplace=True)

删除行

# 删除特色的行用得少,一般使用切片
df.drop(index=['no1','no2'],
        axis=0,
        inplace=True)

df.drop(df.index[[0,1]],
        axis=0,
        inplace=True)

修改列名

df.rename(columns = {'年':'compute_year',
                     '月/季度':'compute_month', 
                     '员工编号':'code', 
                     '员工姓名':'name', 
                     '职位':'position', 
                     '体系':'system_name',
                     '运营单位':'op_unit_name', 
                     '区域':'sub_area_name',
                     '部门名称':'dept_name', 
                     '员工所属小组': 'sub_dept_name'},
          inplace=True)

数据分组(数值变量)

# cut()数据分组,以连续值变量分组创建新特征
bins = [0, 5, 10, 15, 20]  # 切分的边界
group_names = ['A', 'B', 'C', 'D']  # 每组的标签名
df['new'] = pd.cut(df['old'], bins, labels=group_names) # new就是分组新特征

# qcut只要指定切分个数即可
df.qcut(df['年龄'],4)

数据分列(分类变量)

这个操作和Excel中的分列功能很像,在原始数据表中grade列中包含了两个层级的用户等级信息,现在我们通过数据分列将分级信息进行拆分。数据分列操作使用的是split函数,下面是具体的代码和分列后的结果。

grade_split = pd.DataFrame((x.split('-') for x in loandata.grade),
                           index=loandata.index,
                           columns=['grade','sub_grade'])

完成数据分列操作后,使用merge函数将数据匹配会原始数据表,这个操作类似Excel中的Vlookup函数的功能。通过匹配原始数据表中包括了分列后的等级信息

loandata=pd.merge(loandata,grade_split,right_index=True, left_index=True)

设置索引

# 将列转化为索引
# 将columns中的其中两列:race和sex设置索引,race为一级,sex为二级
# inplace=True 在原数据集上修改的
# 默认情况下,设置成索引的列会从DataFrame中移除, drop=False将其保留下来
adult.set_index(['race','sex'], inplace = True) 

# 取消列索引设置,并自动填充索引
adult.reset_index(level=None, drop=Fasle, inplace=False)

# 索引重塑
df.stack()
df.unstack()

排序

df.b(by=['code'], ascending=False, na_position='first')
df.sort_values(by=['code', 'name'], ascending=False, na_position='first')
# 缺失值NaN默认是排在最后后的,na_position='first'设置为排在最前面

数据筛选/切片

  • []
  • isin
  • loc
  • iloc
  • ix
  • contains
# []只能对 行(row/index) 切片,前闭后开
df[0:3]
df[:4]
df[4:]

# where布尔查找,建立在[]基础之上
df[df["A"]>7]
# 并
df.loc[(df['petal_length']>2)&(df['petal_width']>0.3)] 
# 或
df.loc[(df['petal_length']>2)|(df['petal_width']>0.3)] 
# isin()
# 返回布尔值
df["A"].isin([1,2,3])
df.loc[df['sepal_length'].isin([5.8,5.1])]
# loc :根据名称Label切片
# df.loc[A,B] A是行范围,B是列范围
df.loc[:, ['petal_length','petal_width']]
df.loc[1:4, ['petal_length','petal_width']]
df.loc[['no1','no2'], ['petal_length','petal_width']]
# iloc:切位置,以序列号去切
df.iloc[1:4,:]
# ix:混切
# 名称和位置混切,但效率低,少用
df1.ix[0:3,['sepal_length','petal_width']]
# contains()模糊匹配
# 使用DataFrame模糊筛选数据(类似SQL中的LIKE)
# 使用正则表达式进行模糊匹配,*匹配0或无限次,?匹配0或1次
df_obj[df_obj['套餐'].str.contains(r'.*?语音CDMA.*')] 
# 下面两句效果一致
df[df['商品名称'].str.contains("四件套")]
df[df['商品名称'].str.contains(r".*四件套.*")]

正则表达式

多表拼接

merge 合并

  • pandas.merge可根据一个或多个键将不同DataFrame中的行合并起来

    # 在未指定连接键的情况下,merge会将重叠列的列名当做键
    pd.merge(left, right)
    
    # 指定“on”作为连接键,left和right两个DataFrame必须同时存在“on”列,连接键也可N对N(少用)
    pd.merge(left, right, on="key")
    pd.merge(left, right, on=["key1", "key2"])
    
    # 指定left的连接键为“lkey”,right的连接键为“rkey”
    pd.merge(left,  right,  left_on="lkey",  right_on="rkey")
    
    # suffixes:用于追加到重叠列名的末尾,默认为("_x", "_y")
    pd.merge(left,  right,  on="key",  suffixes=("_left",  "_right"))
    
    # 指定连接方式:“inner”(默认),“left”,“right”,“outer”
    pd.merge(left, right, how="outer")
  • 多对多连接产生的是行的笛卡尔积
  • 常用方式:连接方式为“left”,right的连接键要唯一(去除重复值),通过right的数据补全left的数据索引上的合并(可用join代替,而且join更方便)

  • 当DataFrame的连接键位于其索引中,可以使用 left_index=True 和 right_index=True

    # 索引和索引连接
    pd.merge(left,  right,  left_index=True,  right_index=True)
    
    # "key"和索引连接
    pd.merge(left,  right,  left_on="key",  right_index=True)
    
    # 层次化索引
    pd.merge(left,  right,  left_on=["key1", "key2"],  right_index=True)

join 连接

  • DataFrame的join实例方法,是为了方便实现索引合并

    # 用left的索引和right的索引进行merge
    left.join(right)
    
    # 用left的索引和right的“key”进行merge
    left.join(right, on="key")
    
    # 层次化索引
    left.join(right, on=["key1", "key"])
    
    # join可以合并两张以上的表,而merge只能合并两张表
    left.join([right1, right2], how="outer")

concat 轴向连接

  • pandas.concat可以沿着一条轴将多个表对象堆叠到一起:因为模式how模式是“outer”

    # 默认 axis=0 上下拼接,列column重复的会自动合并
    pd.concat([df1, df2], axis=0)
    
    # axis=1 左右拼接,行raw/index重复的会自动合并
    pd.concat([df1, df2], axis=1)
    
    # 忽略df1和df2原来的index,重新给新的DataFrame设置从0开始的index
    pd.concat([df1,df2],  ignore_index=True)

append

  • 使用场景:表头一致的多张表,进行连接(上下连接)

    df1.append(df2).append(df3)

combin_first 数据填补

  • 使用场景:有两张表left和right,一般要求它们的表格结构一致,数据量也一致,使用right的数据去填补left的数据缺漏

  • 如果在同一位置left与right数据不一致,保留left的数据

    df1.combin_first(df2)

数据聚合&分组运算

groupby

# 单层分组
df.groupby('区域')
# 多层分组
df.groupby(['A','B'])

# 每个分组记录的计数
df.groupby('区域').size()
>>> 区域
    东莞     7528
    中山      520
    佛山     5632
    ...
    dtype: int64
     
# 分组数
len(df.groupby('区域'))
>>> 7

aggregate

grouped = df.groupby(['A','B'])
# 对一个特征一次求得多个统计数
grouped['age'].agg([np.sum, np.mean, np.std])
# 对单一属性统计可以改列名
grouped['age'].agg({"求和":np.sum,"求平均数":np.mean})
# 对不同属性求不同的统计数
grouped.agg({'age':np.mean,'fnlwgt':np.sum})

filter

# filter()
# 过滤分组计数少于1000的分组,在把分组计数大于1000的分组整合成一个DataFrame返回
con1 = lambda s : len(s) > 1000
df1 = grouped.filter(con1)
# 过滤分组age均值小于30的分组
con2 = lambda s : s['age'].mean()>30
df2 = grouped3.filter(con2)

tansformation

# tansformation()
# 会返回一个数据集,这个数据集与group具有相同的索引以及大小 相当分组处理后合并
# 举例说明对数据集进行标准化:
zscore = lambda s : (s - s.mean())/s.std()
df = grouped.transform(zscore)

数据透视表

crosstab

# crosstab() 一般只用与计数的数据透视表
pd.crosstab(index= df['A'],
            columns = [df['B'],df['C']],
            margins =True, 
            dropn=True)

pivot/pivot_table

# Produce 'pivot' table based on 3 columns of this DataFrame.
# Uses unique values from index / columns and fills with values.
# 感觉能使用的场景很少,因为不重复
df.pivot(index, columns, values)

df.pivot_table(values=None, 
               index=None, 
               columns=None, 
               aggfunc='mean', 
               fill_value=None, 
               margins=False, 
               dropna=True, 
               margins_name='All')
# 需求: index 是A ,columns 是 B,C, 我要求E的平均数并且有边
pd.pivot_table(df,
               values = 'E',
               index = 'A',
               columns = ['B','C'],
               aggfunc = [np.mean,np.sum],
               margins = True)

时间序列

时间格式转化

# 转化时间格式
df['time']=pd.to_datetime(df['time'])

时间索引操作

哑编码

pd.get_dummies(data, 
               prefix=None, 
               prefix_sep='_', 
               dummy_na=False, 
               columns=None, 
               sparse=False, 
               drop_first=False)

数据导出

pd.to_csv("XXX.csv",index=False)
from sqlalchemy import create_engine
engine = create_engine('mssql+pymssql://zxadmin:Zx!@#$8888@172.17.180.113/BS_KF')
pd.io.sql.to_sql(df,'payroll',engine,if_exists='append',index=False,chunksize=10000)

数据入库

# pd 1.9以后的版本,除了sqllite,均需要通过sqlalchemy来设置
from sqlalchemy import create_engine
engine = create_engine('mssql+pymssql://zxadmin:Zx!@#$8888@172.17.180.113:8000/BS_KF')
# append:如果表存在,则将数据添加到这个表的后面
# fail:如果表存在就不操作
# replace:如果存在表,删了,重建
pd.io.sql.to_sql(df,'table_name',engine,if_exists='append',index=False,chunksize=10000)
# 关闭连接
engine.dispose() 

技巧

数据集概览

# 整体概况
def birdview(data):
    print(data.shape)
    d = {}
    for col in data.columns:
        if len(list(data[col].unique()))<30:
            d[col]= str(list(data[col].unique()))
        else:
            d[col]= "too much"

    r = pd.DataFrame(pd.Series(d),columns=['values'])\
            .join(pd.DataFrame(data.dtypes,columns=['type']))\
            .join(pd.DataFrame(data.count(),columns=['count']))\
            .join(pd.DataFrame(data.isnull().sum(),columns=['isnull']))
            
    return r.sort_values(by=['values','type',])
def catview(data):
    print("定性数据概况")
    for c in data.columns:
        print(c)
        print(dict(df[c].value_counts()))
def valueview(data):
    print("定值数据概况")
    return data.describe().T\
            .join(pd.DataFrame(data.skew(),columns=['skew']))\
            .join(pd.DataFrame(data.kurt(),columns=['kurt']))

长宽表转换

宽表转换为长表

# 方法一:先用set_index,再用stack,然后还有rename修改下列名
df.set_index(['Company','Name'], inplace = True).stack().reset_index()

# 方法二:melt
df.melt(id_vars=['Company','Name'],
        var_name='Year',
        value_name='Sale')

长表转换为宽表

df.pivot_table(index=['Company','Name'], columns='Year', values='Sale')

行列互换

df.T

转载于:https://www.cnblogs.com/stream886/p/10474661.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python模块-pandas 的相关文章

随机推荐

  • createrepo:创建本地源

    4月20日 createrepo 创建本地源 repodata作为软件的仓库 其目录下有四个必要文件 filelists xml gz other xml gz primary xml gz 和repomd xml md 意思是 metad
  • IDEA 中 .properties文件的中文显示乱码问题的解决办法

    今天使用IDEA 搭建Spring Boot 项目 配置application properties 配置文件 录入中文 在右下角出现如下截图提示语 重新打开application properties 文件出现汉字乱码 依据提示信息修改源
  • “你爱我,我爱你,蜜雪冰城甜蜜蜜“秋天的第一杯奶茶!Python安排!!

    立秋了 大家秋天的第一杯奶茶都安排上了么 前一段时间我相信很多人都被 你爱我 我爱你 蜜雪冰城甜蜜蜜 这首歌洗脑了 所以今天就爬取了某度地图上蜜雪冰城门店分布 看看全国有多少家蜜雪冰城 能不能满足大家的需求啦 哈哈哈 数据采集 首先 我们打
  • Linux部署宝塔

    1 linux服务器安装宝塔 宝塔地址 https www bt cn new download html 点击上方地址 进入下方页面 点击安装版本 复制第一个命令 得确认你服务器是centos 远程连接服务器 复制此命令运行 运行成功后
  • [CISCN2019 华东南赛区]Web11 SSTI

    这道SSTI 差点给我渗透的感觉了 全是API 我还想去访问API看看 发现这里读取了我们的ip 我们抓包看看是如何做到的 没有东西 我们看看还有什么提示 欸 那我们可不可以直接修改参数呢 我们传递看看 发现成功了 是受控的 这里我就开始没
  • mysql某批量更新导致死锁

    查询当前数据库全部线程 show full processlist 查询当前运行的全部事务 select from information schema innodb trx 查询锁情况 select from information sc
  • 碰撞改变材质颜色_bp

    感谢来自程序员的暴击 学习资料来于 https www bilibili com video BV125411h7c4 p 22 最大的收获是 材质编辑器上 1维向量到4维向量的生成 会者不难 难者不会 方法很简单 鼠标左键 数字1就会生成
  • 2023年电赛E题完整设计暨电赛全记录

    目录 一 2023年E题完整设计 lt 1 gt 选择方案 任务一 实现按键按下复位 基础部分 任务二 实现激光点绕边框一周 基础部分 任务三 实现激光点绕A4纸边缘一周 基础部分 任务四 实现绿色激光追踪红色激光 发挥部分 lt 2 gt
  • 【信号与系统】傅里叶变换

    傅里叶变换 文章目录 傅里叶变换 傅里叶级数 基本公式 常用公式 基本性质 其他公式 卷积公式 周期信号的傅里叶变换 抽样信号的傅里叶变换 提供延时的理想滤波器 无失真传输 傅里叶级数 https blog csdn net lafea a
  • 【Flink】Flink 消费kafka报错 AMRMClientAsyncImpl Interrupted while waiting for queue InterruptedException

    1 背景 一个flink etl程序 读取一个kafka集群的数据 到两外一个集群 然后报错 2020 06 06 15 56 00 PM Thread flink akka actor default dispatcher 20 Clas
  • redis缓存一致性延时双删代码实现

    不废话 如下 1 自定义注解 author caoyue 延时双删 Retention RetentionPolicy RUNTIME Documented Target ElementType METHOD public interfac
  • shell脚本判断变量是否包含某个字符串的几种方法

    方法一 利用grep查找 strA long string strB string result echo strA grep strB if result then echo 包含 else echo 不包含 fi 先打印长字符串 然后在
  • 利用SVG滤镜实现水波倒影效果

    SVG滤镜用来增加对SVG图形的特殊效果 多种滤镜巧妙结合起来可以实现很棒的视觉效果 下面利用svg的feTurbulence滤镜和feDisplacementMap来模拟真实的水波倒影特效 效果如下图 代码并不复杂 首先设置两张图片 di
  • 数据包络分析(DEA)——CCR模型

    写在前面 博主本人大学期间参加数学建模竞赛十多余次 获奖等级均在二等奖以上 为了让更多学生在数学建模这条路上少走弯路 故将数学建模常用数学模型算法汇聚于此专栏 希望能够对要参加数学建模比赛的同学们有所帮助 目录 1 模型原理 1 1 模型介
  • 如何搭建以太坊测试链(附教程)

    在以太坊项目实际开发中 我们必须要有一个测试环境 因为产品环境是需要消耗GAS的 因此我们希望在测试环境测试无误之后再发布到产品环境以太坊链上去 本篇教程讲述如何搭建本地的测试链 1 Testnets 以太坊的测试网络环境被称为Testne
  • LeetCode 125. 验证回文串

    题目链接 https leetcode cn problems valid palindrome 思路如下 双指针 一首一尾 相向扫描 每次将两个指针分别移动到下一个字母字符或数字字符 再判断这两个指针指向的字符是否相同 C 代码如下 cl
  • Vue为数字添加逗号分隔

    1 看代码 我将这个代码作为外部js导出了 如果你没有那么多模块 就直接CTRL cv 这个方法 丢到你的 vue代码 methods中就可以用了 export const numberFilter function value cut 2
  • Java Class Version 研究

    一 要解决的问题 我们在尝鲜 JDK1 5 的时候 相信不少人遇到过 Unsupported major minor version 49 0 错误 当时定会茫然不知所措 因为刚开始那会儿 网上与此相关的中文资料还不多 现在好了 网上一找就
  • Mac平台安卓模拟器:网易MuMu mac中文免费版(支持12系统)

    网易MuMu Mac版是一款可以让Mac用户在电脑上轻松玩手游的安卓模拟器 是迄今为止国内最好最流畅的手游模拟器软件 网易mumu mac版现已支持梦幻西游 大话西游 倩女幽魂等众多经典安卓手机游戏 mumu模拟器mac版为大家提供海量免费
  • Python模块-pandas

    目录 数据读取 数据探索 数据清洗 数据清洗 类型转换 缺失值 重复值 值替换 修改表结构 新增列 删除列 删除行 修改列名 数据分组 数值变量 数据分列 分类变量 设置索引 排序 数据筛选 切片 多表拼接 数据聚合 分组运算 groupb