数据分析与AI(五)pandas的数据拼接操作/美国各州人口分析/苹果历年股票曲线图

pandas的拼接操作

pandas的拼接分为两种:
- 级联: pd.concat, pd.append
- 合并: pd.merge, pd.join

0. 回顾numpy的级联

import numpy as np
import pandas as pd

from pandas import Series, DataFrame
import matplotlib.pyplot as plt
nd = np.random.randint(0,150,size=(5,4))
nd
# 结果如下:
array([[ 54,  65,  70,  31],
       [  5,  85,  36, 137],
       [ 87,  38,  63,  77],
       [ 89,  82,  58,  96],
       [145, 125,  89,  84]])
# 列级联
np.concatenate([nd,nd], axis=1)
# 结果如下:
array([[ 54,  65,  70,  31,  54,  65,  70,  31],
       [  5,  85,  36, 137,   5,  85,  36, 137],
       [ 87,  38,  63,  77,  87,  38,  63,  77],
       [ 89,  82,  58,  96,  89,  82,  58,  96],
       [145, 125,  89,  84, 145, 125,  89,  84]])

为方便讲解,我们首先定义一个生成DataFrame的函数:

def make_df(cols, index):
    data = {col:[str(col)+str(ind) for ind in index] for col in cols}

    df = DataFrame(data= data, columns = cols, index = index)

    return df
df1 = make_df(['a','b','c'],[1,2,3])
df1
# 结果如下:

这里写图片描述

df2 = make_df(['a','b','c'],[4,5,6])
df2
# 结果如下:

这里写图片描述

1. 使用pd.concat()级联

pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:

pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
          keys=None, levels=None, names=None, verify_integrity=False,
          copy=True)

1) 简单级联

和np.concatenate一样,优先增加行数(默认axis=0)

# np.concatenate(axis=1)的情况是水平级联, np中没有index, 和columns 所以只要行列相等就可以级联
# 在pd中, 如果行 和 列 不一致, 但是shape(形状)相同, 会级联成一个更大的df, 但是不对应的值会填充NaN
pd.concat([df1, df2], axis=1)
# 结果如下:

这里写图片描述
可以通过设置axis来改变级联方向

pd.concat([df1, df2], axis=0)
# 结果如下:

这里写图片描述
注意index在级联时可以重复

df3 = make_df(['a','b','c'],[2,3,4])
df3
# 结果如下

这里写图片描述

pd.concat([df1,df3],axis=1)
# 水平合并以后结果如下:

这里写图片描述
也可以选择忽略ignore_index,重新索引

# git中有 .gitignore 这个文件, 会把写入的文件路径给屏蔽, 不会被上传到github
# add . commit push
# ignore_index 作用是对索引重新排序
pd.concat([df1,df3],axis=0, ignore_index=True)

# 在工作中, 大部分的分析数据来源于mysql,mysql中的id都是唯一的, 分表

# mysql在面试中是最重要的,分表  每个表最大的储存限制是100w条, 一般只会使用80W条是最优的

这里写图片描述
或者使用多层索引 keys

concat([x,y],keys=[‘x’,’y’])

df4 = pd.concat([df1,df3],keys=['期中','期末'])
df4
# 结果如下:

这里写图片描述

2) 不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
有3种连接方式:

  • 外连接:补NaN(默认模式)
df1
# 结果如下:

这里写图片描述

df5 = make_df(['c','d','e'],[3,4,5])
df5
# 结果如下:

这里写图片描述

# concat默认使用的外连接
df6 = pd.concat([df1,df5],axis=0)
df6
# 结果如下:

这里写图片描述

  • 内连接:只连接匹配的项
# 回忆mysql中, outer和inner的不同
# 外连接  left 以左边的表中的数据为核心, 右边数据不匹配,则填充Null
# 内连接 join 两边表数据不完全对应的话, 会只显示能对应上的数据
# join  默认值是outer
df6 = pd.concat([df1,df5],axis=1, join='inner')
df6

# 同mysql一致

这里写图片描述

  • 连接指定轴 join_axes
df1
# 结果如下:

这里写图片描述

df5
# 结果如下:

这里写图片描述

df7 = pd.concat([df1, df5], join_axes=[df1.columns])
df7

# join_axes 的值 是一个列表[df1.index]
# select df1.a, df1.b , df1.c from df1 left join df5 using(c);
# using(c) 相当于: on df1.c=df5.c

这里写图片描述

3) 使用append()函数添加

由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加

append 和 concat相似

df1
# 结果如下:

这里写图片描述

df2
# 结果如下:

这里写图片描述

# 垂直
df1.append(df2)

这里写图片描述

2. 使用pd.merge()合并

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

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

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

1) 一对一合并

df1
# 结果如下:

这里写图片描述

df2
# 结果如下:

这里写图片描述

# 默认是内连接, 表的两边数据都不对应
pd.merge(df1,df2)
# 结果如下

这里写图片描述

display(df1,df5)

这里写图片描述

how的取值 : {‘left’, ‘right’, ‘outer’, ‘inner’}, default ‘inner’

pd.merge(df1,df5, how='right')
# 结果如下:

这里写图片描述

pd.merge(df1,df5,how='left')
# 结果如下:

这里写图片描述

2) 多对一|一对多合并

df1
# 结果如下:

这里写图片描述

df8 = make_df(['c','d','e'],[1,1,1,4])
df8
# 结果如下:

这里写图片描述

pd.merge(df1,df8)

# select * from df1 join df8 on df1.c= df8.c

这里写图片描述

pd.merge(df1,df8, how='left')
# 结果如下:

这里写图片描述

pd.merge(df1,df8,how='outer')

# 在工作中用outer , 可以自动分配

这里写图片描述

pd.merge(df1,df8,how='right')
# 结果如下:

这里写图片描述

3) 多对多合并

df8
# 结果如下:

这里写图片描述

df8.iloc[0]['d'] = 'qwe'
df8['e'][4] = 'asd'
df9 = make_df(list('abd'),[1,1,4,4])
df9
# 结果如下;

这里写图片描述

pd.merge(df9, df8)
# 结果如下:

这里写图片描述

pd.merge(df9, df8,how='outer')
# 结果如下:

这里写图片描述

4) key的规范化

  • 使用on=显式指定哪一列为key,当有多个key相同时使用
df1
# 结果如下:

这里写图片描述

# on的作用是将两个表中相同数据类型, 含义一致的字段进行连接的
pd.merge(df1,df10, left_on='c',right_on='w')
# mysql
# select * 

这里写图片描述

df11 = make_df(list('bcd'),[1,2,3])
df11
# 结果如下:

这里写图片描述

pd.merge(df1,df11,on='b')

# mysql中一般碰到两个字段相同, 但是代表的含义不一样, 或者数据类型不同
# a.u = b.u  a.o - b.o
# select a.o a_o, b.o b_o

这里写图片描述

6) 列冲突的解决

当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名

可以使用suffixes=自己指定后缀

pd.merge(df1,df11,on='c',suffixes=('_up','_down'))
# 结果如下:

这里写图片描述

U.S.A人口分析

United States America

import pandas as pd
from pandas import DataFrame, Series
# 先导入数据文件

# 各州的面积
areas = pd.read_csv('../data/state-areas.csv')
# 缩写
abbr = pd.read_csv('../data/state-abbrevs.csv')
# 人口
pop = pd.read_csv('../data/state-population.csv')
areas.head()
pop.head()
# 结果如下:

这里写图片描述
这里写图片描述

# 开始合并
abbrToPop = pd.merge(abbr,pop, left_on='abbreviation', right_on='state/region', how='outer')
abbrToPop.head()
# 合并结果如下:

这里写图片描述

# 将重复的列删除掉
# .drop()
# 一般的一执行完就打印的, 这种形式的方法不对原数据产生影响, inplace代表是否对原数组产生影响
abbrToPop.drop(columns='abbreviation', inplace=True) # 或者abbrToPop.drop(labels='abbreviation', axis=1)
# 空数据一般会显示NaN
abbrToPop.isnull().any()
# 结果如下:
state            True
state/region    False
ages            False
year            False
population       True
dtype: bool   # 其中返回True的字段中存在NAN空数据, 需要进行处理
# 怎么计算丢失数据的数量
# state  population
abbrToPop['state'].isnull().sum()
# 结果如下:  96
# 把空数据填充上, 得到NAN行的筛选条件
cond = abbrToPop['state'].isnull()

# state是州名, 如何填充
# unique()去除重复的值
abbrToPop['state/region'][cond].unique()
# 结果如下:array(['PR', 'USA'], dtype=object)
# 我们通过翻阅资料查到了PR的全称
# Puerto Rico
# 开始赋值
cond_pr = abbrToPop['state/region'] == 'PR'
abbrToPop['state'][cond_pr] = 'Puerto Rico'
cond_usa = abbrToPop['state/region'] == 'USA'
abbrToPop['state'][cond_usa] = 'United States'
abbrToPop.isnull().any()
# 结果如下:
state           False
state/region    False
ages            False
year            False
population       True
dtype: bool   # 成功将state数据修复
abbrToPop.dropna(inplace=True)
# population 查阅资料, 我们先删除掉
abbrToPop.isnull().sum()
# 结果:
state           0
state/region    0
ages            0
year            0
population      0
dtype: int64
# 还有一个表需要合并
areas.head()
# 结果如下

这里写图片描述

# 融合面积
abbrToPopToAreas = pd.merge(abbrToPop,areas, on='state',how='outer' )
abbrToPopToAreas.head()

这里写图片描述

abbrToPopToAreas.isnull().sum()
# 结果如下:
state             0
state/region      0
ages              0
year              0
population        0
area (sq. mi)    48
dtype: int64   # area字段有48个空值
cond_area = abbrToPopToAreas['area (sq. mi)'].isnull()
total_area = areas['area (sq. mi)'].sum()
total_area  # 结果是: 3790399
# U.S.A
cond_ab = abbrToPopToAreas['state/region'] == 'USA'

abbrToPopToAreas['area (sq. mi)'][cond_ab] = total_area
abbrToPopToAreas.isnull().sum()
# 数据处理完毕后结果:
state            0
state/region     0
ages             0
year             0
population       0
area (sq. mi)    0
dtype: int64
# 现在的表已经完全融合完成了
# 现在可以进行分析了

找出2010年全民人口数据, df.query()

abbrToPopToAreas_2010 = abbrToPopToAreas.query('year == 2010 & ages == "total"')
abbrToPopToAreas_2010.head()
# 结果如下:

这里写图片描述

以state作为列索引

# 工作中会使用id作为列的索引
# set_index()
abbrToPopToAreas_2010.set_index('state', inplace=True)
abbrToPopToAreas_2010.head()

这里写图片描述

计算人口的密度, population / area (sq. mi)

density_2010 = abbrToPopToAreas_2010['population'] / abbrToPopToAreas_2010['area (sq. mi)']
density_2010
# 结果如下:
state
Alabama                   91.287603
Alaska                     1.087509
Arizona                   56.214497
Arkansas                  54.948667
California               228.051342
Colorado                  48.493718
Connecticut              645.600649
Delaware                 460.445752
District of Columbia    8898.897059
Florida                  286.597129
Georgia                  163.409902
Hawaii                   124.746707
Idaho                     18.794338
Illinois                 221.687472
Indiana                  178.197831
Iowa                      54.202751
Kansas                    34.745266
Kentucky                 107.586994
Louisiana                 87.676099
Maine                     37.509990
Montana                    6.736171
Nebraska                  23.654153
Nevada                    24.448796
New Hampshire            140.799273
New Jersey              1009.253268
New Mexico                16.982737
New York                 356.094135
North Carolina           177.617157
North Dakota               9.537565
Ohio                     257.549634
Oklahoma                  53.778278
Oregon                    39.001565
Maryland                 466.445797
Massachusetts            621.815538
Michigan                 102.015794
Minnesota                 61.078373
Mississippi               61.321530
Missouri                  86.015622
Pennsylvania             275.966651
Rhode Island             681.339159
South Carolina           144.854594
South Dakota              10.583512
Tennessee                150.825298
Texas                     93.987655
Utah                      32.677188
Vermont                   65.085075
Virginia                 187.622273
Washington                94.557817
West Virginia             76.519582
Wisconsin                 86.851900
Wyoming                    5.768079
Puerto Rico             1058.665149
United States             81.607845
dtype: float64

2010年的人口密度融合到表中

abbrToPopToAreas_2010['density_2010'] = density_2010
abbrToPopToAreas_2010.head()

这里写图片描述

排序,找出人口密度最高的五个州¶

# sort_values 根据值来进行排序

abbrToPopToAreas_2010.sort_values(by='density_2010').tail()

这里写图片描述

苹果股票涨跌图绘制

import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import numpy as np
apple = pd.read_csv('../data/AAPL.csv')
apple.head()
# 结果如下:

这里写图片描述

apple.dtypes
# 结果如下:
Date          object
Open         float64
High         float64
Low          float64
Close        float64
Adj Close    float64
Volume       float64
dtype: object  # 在这里可以看见Date是object类型的

转换一下data的数据类型

mysql 中有datetime pd .to_datetime()

apple['Date'] = pd.to_datetime(apple['Date'])
apple.dtypes
# 结果如下:
Date         datetime64[ns]
Open                float64
High                float64
Low                 float64
Close               float64
Adj Close           float64
Volume              float64
dtype: object    # Date的数据类型转换为datetime64
apple.set_index('Date', inplace=True)
# 结果如下:

这里写图片描述

绘制图形

adj_plot = apple['Adj Close'].plot()
fig = adj_plot.get_figure()

# set_size_inches 设置图片的大小, 单位是英寸
fig.set_size_inches(12,6)
# 结果如下:

这里写图片描述

# 因为Volume这一列数据量级太大,不适合分析,故删除
apple.drop('Volume', axis=1, inplace=True)
app = apple.plot()
fig1 = app.get_figure()
fig1.set_size_inches(12,6)

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_41637554/article/details/80738962