数据分析之DataFrame基本操作

导包

import numpy as np
import pandas as pd 
from pandas import DataFrame,Series

DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values

DataFrame的创建

  • 最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
  • 此外,DataFrame会自动加上每一行的索引。使用字典创建的DataFrame后,则columns参数将不可被使用。同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。
  • DataFrame属性:values、columns、index、shape
dic={
    'xiaoming':[88,66,55],
    'lingling':[99,77,33],
    'xiaoli':[55,88,65]
}

df1=DataFrame(data=dic,index=['语文','数学','英语'])
df1
lingling    xiaoli  xiaoming
语文  99  55  88
数学  77  88  66
英语  33  65  55

根据添加行索引添加行数据

df1.loc['物理']=[55,84,66]
df1

lingling    xiaoli  xiaoming
语文  99  55  88
数学  77  88  66
英语  33  65  55
物理  55  84  66

根据添加列索引添加列数据

df1['xixi']=[88,55,44,11]
df1

lingling    xiaoli  xiaoming    xixi
语文  99  55  88  88
数学  77  88  66  55
英语  33  65  55  44
物理  55  84  66  11

对列进行索引

  • 通过类似字典的方式 df[‘q’]
  • 通过属性的方式 df.q
  • 可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

对行进行索引

  • 使用.loc[]加index来进行行索引
  • 使用.iloc[]加整数来进行行索引
  • 同样返回一个Series,index为原来的columns。

使用行索引(iloc[3,1] or loc[‘C’,’q’]) 行索引在前,列索引在后


df.iloc[1,2]

df.loc['语文','xiaoli']

行切片

df1['语文':'英语']

列切片

df1.loc[:,'lingling':'xiaoming']
  • 直接用中括号时:
  • 索引表示的是列索引
  • 切片表示的是行切片

DataFrame的运算

  • 每个元素进行+-*/
df1+1
  • DataFrame之间的运算,同Series一样:
  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
df2=DataFrame(data=np.random.randint(1,100,(4,4)),index=['A','B','C','D'],
             columns=['a','b','c','d'])
df2
df1+df2

pandas处理空值操作

  • isnull()
  • notnull()
  • dropna(): 过滤丢失数据
  • fillna(): 填充丢失数据
  • df.notnull().any()/all()来判断每行是否有空值
df3=DataFrame(data=np.random.randint(1,100,(4,5)),index=['A','B','C','D'],
             columns=['a','b','c','d','e'])
df3

df3.loc['A','b']=None
df3.loc['B','c']=None
df3

df3.notnull().all()

判断哪一行有空值

df3.notnull().all(axis=1)

过滤掉有空值的行

df3[df3.notnull().all(axis=1)]

删除空值,默认删除行,设置axis=1删除列

df3.dropna(axis=1)

填充空值

df3.fillna(66)

创建多层列索引

  • 隐式构造
df=DataFrame(data=np.random.randint(60,120,size=(2,4)),
         columns=[['qizhong','qizhong','qimo','qimo'],['chinese','math','chinese','math']],
         index=['tom','jay'])
  • 显示构造pd.MultiIndex.from_,使用product创建
col=pd.MultiIndex.from_product([['qizhong','qimo'],
                                ['chinese','math']])
df=DataFrame(data=np.random.randint(60,120,(2,4)),columns=col,index=['tom','bill'])
  • 多层列索引
df['qizhong']['math']

多层行索引

df.loc['tom']['qizhong']['math']

索引的堆(stack):对矩阵的索引进行变换处理

  • stack():把列索引变成行索引 (从上到左)
  • unstack():把行索引变成列索引(从左到上)
  • level=0,代表最外层索引,level=1代表第二层索引
df.stack(level=0)

df.unstack()

聚合操作

  • 所谓的聚合操作:平均数,方差,最大值,最小值……
  • df.mean(),df.max(),df.min()…..
df2.max(axis=1)

pandas的拼接操作

  • pandas的拼接分为两种:
  • 级联:pd.concat, pd.append
  • 合并:pd.merge, pd.join
  • 使用pd.concat()级联
  • pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
    • objs
    • axis=0
    • keys
    • join=’outer’ / ‘inner’:表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
    • ignore_index=False
df5=DataFrame(data=np.random.randint(1,100,(4,4)),index=['A','B','C','D'],
             columns=['a','b','c','d'])
df6=DataFrame(data=np.random.randint(1,100,(4,4)),index=['A','B','C','D'],
             columns=['a','b','c','d'])

pd.concat([df5,df6],ignore_index=True)

不匹配级联

  • 不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
  • 有2种连接方式:
    • 外连接:补NaN(默认模式)
    • 内连接:只连接匹配的项
pd.concat([df1,df2])

使用pd.merge()合并

  • merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并
    使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
    注意每一列元素的顺序不要求一致
  • 参数:
    • how:out取并集 inner取交集
    • on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表
  • 一对一合并
df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                'group':['Accounting','Engineering','Engineering'],
                })
df2 = DataFrame({'employee':['Lisa','Bob','Jake'],
                'hire_date':[2004,2008,2012],
                })
pd.merge(df1,df2)

列冲突的解决

  • 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
  • 可以使用suffixes=自己指定后缀
df8 = DataFrame({'name':['Peter','Paul','Mary'],
                'rank':[1,2,3]})

df9 = DataFrame({'name':['Peter','Paul','Mary'],
                'rank':[5,6,7]})

pd.merge(df8,df9,on='name')

pd.merge(df8,df9,on='name',suffixes=['_L','_R'])

删除行重复元素

  • 使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True
  • keep参数:指定保留哪一重复的行数据‘first’,‘last’,False
df5.loc['A']=66
df5.loc['C']=66

查找每行的重复值,返回布尔值

df5.duplicated(keep=False)
  • 使用drop_duplicates()函数删除重复的行
drop_duplicates(keep='first/last'/False)
  • inplace=True会改变数据,彻底删除
df5.drop_duplicates(keep='first')

映射

  • 映射的含义:创建一个映射关系列表(一般用字典表示),把values元素和一个特定的标签或者字符串绑定(给一个元素值提供不同的表现形式)
  • 包含三种操作:
    • replace()函数:替换元素
    • 最重要:map()函数:新建一列
    • rename()函数:替换索引
  • Series替换操作

    • 单值替换
    • 普通替换
    • 字典替换(推荐)
    • 多值替换
    • 列表替换
  • 参数

    • to_replace:被替换的元素
    • value:替换后的元素
s=Series(np.random.randint(1,100,6))
s

0    79
1    14
2    61
3    49
4    46
5    55
dtype: int32

单值映射

s.replace(to_replace=55,value=66)

0    79
1    14
2    61
3    49
4    46
5    66
dtype: int32

多值列表映射

s.replace(to_replace=[14,46],value=[55,88])

0    79
1    55
2    61
3    49
4    88
5    55
dtype: int64

多值字典映射

s.replace(to_replace={79:100,
                      49:111
                     })
0    100
1     14
2     61
3    111
4     46
5     55
dtype: int64
  • DataFrame使用replace同理Series,根据行索引,列索引,单个值进行替换
  • map()函数:新建一列 , map函数并不是df的方法,而是series的方法
  • map(字典) 字典的键要足以匹配所有的数据,否则出现NaN: —df[‘c’].map({85:’bw’,100:’yb’})
  • map()可以映射新一列数据
  • map()中可以使用lambd表达式
  • map()中可以使用方法,可以是自定义的方法
  • eg:map({to_replace:value})
  • 注意 map()中不能使用sum之类的函数,for循环
dic={
    'name':['xiaoming','zhangsan'],
    'age':[23,33]
}
df=DataFrame(data=dic)
df
age name
0   23  xiaoming
1   33  zhangsan

创建映射关系

e_name=df.name.map({'xiaoming':'bill',
                   'zhangsan':'jack'})
e_name
Out[23]:
0    bill
1    jack
Name: name, dtype: object
In [24]:

增加一列

df['e_name']=e_name
df
age name    e_name
0   23  xiaoming    bill
1   33  zhangsan    jack
  • map(func),可以传递自定义函数
  • 注意:并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数

自定义 函数,使传入的参数+1

def func(s):
    return s+1

调用自定义函数 ,使得年龄+1

df.age.map(func)

map(lambda 函数)

  • 使得年龄+1
df.age.map(lambda s:s+1)

rename()函数:替换索引

  • 使用rename()函数替换行索引
    • index 替换行索引
    • columns 替换列索引
    • level 指定多维索引的维度
df4 = DataFrame({'color':['white','gray','purple','blue','green'],'value':np.random.randint(10,size = 5)})

改变行索引

df4.rename(index={0:'zero',
                 1:'one',
                 2:'two',
                 3:'three',
                 4:'four'})

改变列索引

df4.rename(columns={'color':'cl',
                   'value':'num'})

使用聚合操作对数据异常值检测和过滤

  • 使用df.std()函数可以求得DataFrame对象每一列的标准差
  • 创建一个1000行3列的df 范围(0-1),求其每一列的标准差
df=DataFrame(np.random.random((1000,3)))
df.std(axis=0)
  • 保留小于两倍的第一列数据
df[0]<df[0].std()*2
  • 将布尔值True作为行索引
df[df[0]<df[0].std()*2]

给索引排序

  • 使用.take()函数排序
  • take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序,axis=0,代表行索引
  • eg:df.take([1,3,4,2,5])
  • 可以借助np.random.permutation()函数随机排序
    In [49]:
df=DataFrame(data=np.random.randint(0,100,size=(4,5)))
df.take([4,3,1,2,0],axis=1)

随机排序

df.take(np.random.permutation(5),axis=1)

数据分类处理【重点】

  • 数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
  • 数据分类处理:
    • 分组:先把数据分为几组
    • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来
    • 数据分类处理的核心:
  • groupby()函数
  • groups属性查看分组情况
df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'],
                'price':[4,3,3,2.5,4,2],
               'color':['red','yellow','yellow','green','green','green'],
               'weight':[12,20,50,30,20,44]})

分组后进行聚合操作

df.groupby(by='color')['price'].mean()

color
green     2.833333
red       4.000000
yellow    3.000000
Name: price, dtype: float64
  • 找出哪些行是苹果的信息 使用==进行判断
df['item']=='Apple'
df[df['item']=='Apple']
  • 按颜色查看各种颜色的水果的平均价格,并将各种颜色水果的平均价格和df进行汇总
df.groupby(by='color')['price'].mean()
c_price_mean=df['color'].map({
    'green':2.83,
    'red':4,
    'yellow':3
})
df['c_price_mean']=c_price_mean

高级数据聚合

  • 使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算
  • df.groupby(‘item’)[‘price’].sum() <==> df.groupby(‘item’)[‘price’].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
  • 注意
    • transform 会自动匹配列索引返回值,不去重
    • apply 会根据分组情况返回值,去重
def func(s):
    sum=0
    for i in s:
        sum+=i
    return sum/s.size
df.groupby(by='item')['price'].apply(func)
df.groupby(by='item')['price'].transform(lambda s:s+1)

猜你喜欢

转载自blog.csdn.net/qq_42055440/article/details/81210062