python爬虫---pandas的操作

pandas的操作

pandas的拼接操作

# pandas的拼接操作
    级联  pd.concat , pd.append
    合并  pd.merge , pd.join 

一丶pd.concat()级联

# pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
  # 参数说明:  
        objs
        axis=0  # 方向  1 是 行, 0是 列
        keys
        join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
        ignore_index=False  # 忽略索引
import pandas as pd
import numpy as np
from pandas import DataFrame,Series

# 准备数据
df1 = DataFrame(data=np.random.randint(0,100,size=(3,4)))
df2 = DataFrame(data=np.random.randint(0,100,size=(3,4)))

# 1. 匹配级联
    pd.concat((df1,df2),axis=0) # 列 
    
# 2.不匹配级联
    # 不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
    # 两种连接方式: 
        # 外连接: 补充NaN 默认模式 outer
         pd.concat((df1,df2),axis=0,join='outer') # 包含空值
            
        # 内连接: 只连接匹配的项  inner
        pd.concat((df1,df2),axis=0,join='inner') # inner 内连接(df1,和df2共有的列或行,空值行列剔除)

二丶pd.merge()合并

# 1.merge与concat的区别在于,merge需要依据某一共同的列来进行合并

# 2.使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。

# 3.注意每一列元素的顺序不要求一致


# 参数:
    how:out取并集 inner取交集
    on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表
# 1. 一对一合并  
    # 数据准备
    df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                    'group':['Accounting','Engineering','Engineering'],
                    })
    df2 = DataFrame({'employee':['Lisa','Bob','Jake'],
                    'hire_date':[2004,2008,2012],
                    })

        # 合并 (employee是 合并条件)
        pd.merge(df1,df2)
    
    
# 2. 多对一合并    
    df3 = DataFrame({
        'employee':['Lisa','Jake'],
        'group':['Accounting','Engineering'],
        'hire_date':[2004,2016]})
    df4 = DataFrame({'group':['Accounting','Engineering','Engineering'],
                           'supervisor':['Carly','Guido','Steve']
                    })

        # 合并 (group 是合并条件)
        pd.merge(df3,df4)
  

# 3. 多对多合并
    df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                     'group':['Accounting','Engineering','Engineering']})
    df5 = DataFrame({'group':['Engineering','Engineering','HR'],
                    'supervisor':['Carly','Guido','Steve']
                    })
    #  合并 how指定合并的列
    pd.merge(df1,df5,how='right')
    
    
# 4.key的规范化
    # 1. 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名,suffixes=自己指定后缀 (默认是x和y)
    
    df1 = DataFrame({'employee':['Jack',"Summer","Steve"],
                 'group':['Accounting','Finance','Marketing']})
    df2 = DataFrame({'employee':['Jack','Bob',"Jake"],
                 'hire_date':[2003,2009,2012],
                'group':['Accounting','sell','ceo']})
    # 合并
    pd.merge(df1,df2,on='employee')
     # 结果: group_x  group_y hire_date
    
    
    # 2. 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
    df5 = DataFrame({'name':['Lisa','Bobs','Bill'],
                'hire_dates':[1998,2016,2007]})
    
    # 合并 
    pd.merge(df1,df5,left_on='employee',right_on='name',how='outer')
#### 总结: 合并
### 内合并与外合并:out取并集 inner取交集
# 内合并:只保留两者都有的key(默认模式)

df6 = DataFrame({'name':['Peter','Paul','Mary'],
               'food':['fish','beans','bread']}
               )
df7 = DataFrame({'name':['Mary','Joseph'],
                'drink':['wine','beer']})
                
# 外合并 how='outer':补NaN
                
df6 = DataFrame({'name':['Peter','Paul','Mary'],
               'food':['fish','beans','bread']}
               )
df7 = DataFrame({'name':['Mary','Joseph'],
                'drink':['wine','beer']})

案例:人口分析

# coding: utf-8

# - 需求:
#     - 导入文件,查看原始数据
#     - 将人口数据和各州简称数据进行合并
#     - 将合并的数据中重复的abbreviation列进行删除
#     - 查看存在缺失数据的列
#     - 找到有哪些state/region使得state的值为NaN,进行去重操作
#     - 为找到的这些state/region的state项补上正确的值,从而去除掉state这一列的所有NaN
#     - 合并各州面积数据areas
#     - 我们会发现area(sq.mi)这一列有缺失数据,找出是哪些行
#     - 去除含有缺失数据的行
#     - 找出2010年的全民人口数据
#     - 计算各州的人口密度
#     - 排序,并找出人口密度最高的五个州   df.sort_values()


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

# 读取数据
abb = pd.read_csv('./data/state-abbrevs.csv')
abb.head(2)

pop = pd.read_csv('./data/state-population.csv')
pop.head(2)

area = pd.read_csv('./data/state-areas.csv')
area.head(2)



### 数据合并
    #将人口数据和各州简称数据进行合并
    abb_pop = pd.merge(abb,pop,left_on='abbreviation',right_on='state/region',how='outer')
    abb_pop.head(2)


    #将合并的数据中重复的abbreviation列进行删除
    abb_pop.drop(labels='abbreviation',axis=1,inplace=True)
    abb_pop.head(2)


    #查看存在缺失数据的列
    abb_pop.isnull().any(axis=0)


    
###  一    
# 找到有哪些state/region使得state的值为NaN,进行去重操作

    #1.state列中哪些值为空
    abb_pop['state'].isnull()




    #2.可以将step1中空对应的行数据取出(state中的空值对应的行数据)
    abb_pop.loc[abb_pop['state'].isnull()]



    #3.将对应的行数据中指定的简称列取出
    abb_pop.loc[abb_pop['state'].isnull()]['state/region'].unique()



###  二
#为找到的这些state/region的state项补上正确的值,从而去除掉state这一列的所有NaN
    #1.先将USA对应的state列中的空值定位到
    abb_pop['state/region'] == 'USA'



    #2,将布尔值作为原数据的行索引,取出USA简称对应的行数据
    abb_pop.loc[abb_pop['state/region'] == 'USA']




    #3.获取符合要求行数据的行索引
    indexs = abb_pop.loc[abb_pop['state/region'] == 'USA'].index




    #4.将indexs这些行中的state列的值批量赋值成united states
    abb_pop.loc[indexs,'state'] = 'United Status'



###  二
 #将PR对应的state列中的空批量赋值成 PUERTO RICO
    abb_pop['state/region'] == 'PR'
    abb_pop.loc[abb_pop['state/region'] == 'PR']
    indexs = abb_pop.loc[abb_pop['state/region'] == 'PR'].index
    abb_pop.loc[indexs,'state'] = 'PUERTO RICO'



###  三    
#合并各州面积数据areas
    abb_pop_area = pd.merge(abb_pop,area,how='outer')
    abb_pop_area.head(3)


###  四
    #我们会发现area(sq.mi)这一列有缺失数据,找出是哪些行
    abb_pop_area['area (sq. mi)'].isnull()

    #将空值对应的行数据取出
    indexs = abb_pop_area.loc[abb_pop_area['area (sq. mi)'].isnull()].index

    #去除含有缺失数据的行
    abb_pop_area.drop(labels=indexs,axis=0,inplace=True)



###  五
    #找出2010年的全民人口数据
    abb_pop_area.query('year == 2010 & ages == "total"')



###  六
    #计算各州的人口密度
    abb_pop_area['midu'] = abb_pop_area['population'] / abb_pop_area['area (sq. mi)']
    abb_pop_area.head(2)

    # 取前5条数据
    abb_pop_area.sort_values(by='midu',axis=0,ascending=False).head(5)

三丶数据处理

删除重复的元素

# 使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True

    # - keep参数:指定保留哪一重复的行数据
# 使用drop_duplicates()函数删除重复的行
   # drop_duplicates(keep='first/last'/False) 
   # 参数说明: first 保留第一行,last保留最后一行 ,False所有行 

映射

# 1 . replace()函数:替换元素


# DataFrame替换操作
    单值替换
        普通替换: 替换所有符合要求的元素:to_replace=15,value='e'
        按列指定单值替换: to_replace={列标签:替换值} value='value'
    多值替换
        列表替换: to_replace=[] value=[]
        字典替换(推荐) to_replace={to_replace:value,to_replace:value}
        
    #  把 6 替换成six
    df.replace(to_replace=6,value='six')
    
    # 字典的形式替换
    df.replace(to_replace={6:'six'})
    
    # to_replac 指定了某个元素进行替换
    df.replace(to_replace={5:6},value='six')
# 2 . map函数:新建一列, map函数并不是df的方法,而是series的方法
    # map()可以映射新一列数据
    # map()中可以使用lambd表达式
    # map()中可以使用方法,可以是自定义的方法

    # eg:map({to_replace:value})

    # 注意 map()中不能使用sum之类的函数,for循环



    #  1. 新增一列:给df中,添加一列,该列的值为中文名对应的英文名
        dic = {
            'name':['张三','周杰伦','张三'],
            'salary':[20000,10000,20000]
        }
        df = DataFrame(data=dic)

        #映射关系表
        dic = {
            '张三':'tom',
            '周杰伦':'jay'
        }
        df['e_name'] = df['name'].map(dic)
        
        
    # 2.map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数)        def after_sal(s):
            return s - (s-3000)*0.5
        
       #超过3000部分的钱缴纳50%的税
       df['after_sal'] = df['salary'].map(after_sal)
       
       # applay() 方法和 map()具有相同的效果  , #apply效率高于map
       df['after_sal'] = df['salary'].apply(after_sal)  #apply效率高于map
    
    
    # 注意: 
        # 并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数。
        

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

### 使用df.std()函数可以求得DataFrame对象每一列的标准差

# 创建一个1000行3列的df 范围(0-1),求其每一列的标准差
    df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
# 对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差
    twice_std = df['C'].std() * 2
    # ~ 取反 , loc[]对值进行过滤(标签索引) 
    df.loc[~(df['C'] > twice_std)]
# 总结:
    # 检测过滤缺失值
        dropna
        fillna
        
    # 检测过滤重复值
        drop_duplicated(keep)
    
    # 检测过滤异常值
        得到鉴定异常值的条件
        将异常值对应的行删除
  

# iloc 和 loc 的区别:  
    # 相同: 
        无论是iloc还是loc 均采用[]而不是括号
            
     # 不同:
        1. 如果只是取行 建议用iloc 因为比较简单
        2. 如果列和行同时取 建议采用loc 因为可以直接定义到标签
        3.iloc:位置索引,和列表索引类似,里面只能是数字
        4.loc:标签索引,只能使用字符型标签来索引数据

五丶排序

### take()函数排序
    # 接收一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序
    # 栗子: eg:df.take([1,3,4,2,5])


# np.random.permutation()函数随机排序
    np.random.permutation(1000)

#列排序,行排序
df.take(indices=np.random.permutation(1000),axis=0).take(indices=np.random.permutation(3),axis=1)
    
# np.random.permutation(x)可以生成x个从0-(x-1)的随机数列
df.take(indices=np.random.permutation(1000),axis=0).take(indices=np.random.permutation(3),axis=1)[0:5]
# 随机抽样
    # 当DataFrame规模足够大时,直接使用np.random.permutation(x)函数,就配合take()函数实现随机抽样

六丶 数据分类处理【重点】

### 数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

    # 数据分类处理:

        # 1. 分组:先把数据分为几组
        # 2. 用函数处理:为不同组的数据应用不同的函数以转换数据
        # 3. 合并:把不同组得到的结果合并起来


# 数据分类处理的核心:

        # 1. groupby()函数
        # 2. groups属性查看分组情况
        # 3. eg: df.groupby(by='item').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]})
               
               
# 使用groupby实现分组 
    df.groupby(by='item',axis=0)
    
# 使用groups查看分组情况
    # 该函数可以进行数据的分组,但是不显示分组情况
    df.groupby(by='item',axis=0).groups
    
# 分组后的聚合操作:分组后的成员中可以被进行运算的值会进行运算,不能被运算的值不进行运算
    
    #给df创建一个新列,内容为各个水果的平均价格
    df.groupby(by='item',axis=0).mean()['price']

    mean_price_series = df.groupby(by='item',axis=0)['price'].mean()
    
    # 映射关系表
    dic = mean_price_series.to_dict()
    df['mean_price'] = df['item'].map(dic)


    # 汇总:将各种颜色水果的平均价格和df进行汇总
    df['color_mean_price'] = df['color'].map(df.groupby(by='color')['price'].mean().to_dict())

高级数据聚合

### 使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算

    # 1. df.groupby('item')['price'].sum() <==>         df.groupby('item')['price'].apply(sum)
    
    # 2. transform和apply都会进行运算,在transform或者apply中传入函数即可
    
    # 3. transform和apply也可以传入一个lambda表达式
# 1. 按照水果类型分组,求出平均价格
    df.groupby(by='item')['price'].mean()
    
    
# 2. 定义函数
def my_mean(s):
    sum = 0
    for i in s:
        sum += i
    return sum/len(s)
    

# transform 函数  和 apply函数 都可以调用自定义的而函数出理数据

# 3.使用apply函数求出水果的平均价格
df.groupby(by='item')['price'].apply(my_mean)  



# 4. 使用transform函数求出水果的平均价格

df.groupby(by='item')['price'].transform(my_mean)

transform() 方法+自定义函数

transform() 方法+python内置方法

apply() 方法+自定义函数

pandas:apply和transform方法的性能比较

案例:美国2012年总统候选人政治献金数据分析

# coding: utf-8

# # 美国2012年总统候选人政治献金数据分析

# 导入包


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


# 方便大家操作,将月份和参选人以及所在政党进行定义



months = {'JAN' : 1, 'FEB' : 2, 'MAR' : 3, 'APR' : 4, 'MAY' : 5, 'JUN' : 6,
          'JUL' : 7, 'AUG' : 8, 'SEP' : 9, 'OCT': 10, 'NOV': 11, 'DEC' : 12}
of_interest = ['Obama, Barack', 'Romney, Mitt', 'Santorum, Rick', 
               'Paul, Ron', 'Gingrich, Newt']
parties = {
  'Bachmann, Michelle': 'Republican',
  'Romney, Mitt': 'Republican',
  'Obama, Barack': 'Democrat',
  "Roemer, Charles E. 'Buddy' III": 'Reform',
  'Pawlenty, Timothy': 'Republican',
  'Johnson, Gary Earl': 'Libertarian',
  'Paul, Ron': 'Republican',
  'Santorum, Rick': 'Republican',
  'Cain, Herman': 'Republican',
  'Gingrich, Newt': 'Republican',
  'McCotter, Thaddeus G': 'Republican',
  'Huntsman, Jon': 'Republican',
  'Perry, Rick': 'Republican'           
 }




df = pd.read_csv('./data/usa_election.txt')
df.head()




#新建一列各个候选人所在党派party
df['party'] = df['cand_nm'].map(parties)
df.head()




#party这一列中有哪些元素
df['party'].unique()




#统计party列中各个元素出现次数
df['party'].value_counts()




#查看各个党派收到的政治献金总数contb_receipt_amt
df.groupby(by='party')['contb_receipt_amt'].sum()




#查看每天各个党派收到的政治献金总数contb_receipt_amt
df.groupby(by=['contb_receipt_dt','party'])['contb_receipt_amt'].sum()




#将表中日期格式转换为'yyyy-mm-dd'  day-m-y
def transformDate(d):
    day,month,year = d.split('-')
    month = months[month]
    return '20'+year+'-'+str(month)+'-'+day
df['contb_receipt_dt'] = df['contb_receipt_dt'].map(transformDate)
df.head()




#查看老兵(捐献者职业)主要支持谁  :查看老兵们捐赠给谁的钱最多
#1.将老兵对应的行数据取出
df['contbr_occupation'] == 'DISABLED VETERAN'
old_bing = df.loc[df['contbr_occupation'] == 'DISABLED VETERAN']




#2.根据候选人分组
old_bing.groupby(by='cand_nm')['contb_receipt_amt'].sum()




df['contb_receipt_amt'].max()




#捐赠金额最大的人的职业以及捐献额  .通过query("查询条件来查找捐献人职业")
df.query('contb_receipt_amt == 1944042.43')

猜你喜欢

转载自www.cnblogs.com/dengl/p/11759168.html