Pandas库

1、掌握DataFrame数据结构的创建和基本性质。
2、掌握Pandas库的数值运算和统计分析方法。
3、掌握DataFrame缺失值处理、数据集合并等操作。
4、掌握DataFrame累计与分组操作。
5、用eval和query实现更高效的计算。

numpy的表现已经很好了,但是当我们需要处理更灵活的数据任务的时候(如为数据添加标签、 处理缺失值、分组等),numpy 的限制就非常明显了,基于numpy而创建的pandas 库提供了一种高效的带行标签和列标签的数据结构DataFrame,完美的解决了上述问题。`

对象创建

Pandas Series对象

Series是带标签数据的一维数组

Series对象的创建

通用结构:pd.Series(data, index=index,dtype=dtype)
-data:数据,可以是列表、字典或Numpy数组

  • index:索引,为可选参数
  • dtype:数据类型,为可选参数

1、用列表创建

  • index缺省时,默认为整数序列
import pandas as pd

data = pd.Series([1.5, 3, 4.5, 6])
print(data)
"""
0    1.5
1    3.0
2    4.5
3    6.0
dtype: float64
"""
# 添加index,数据类型若缺省,则会自动根据传入的数据判断
x = pd.Series([1.5, 3, 4.5, 6], index=["a", "b", "c", "d"])
print(x)
"""
a    1.5
b    3.0
c    4.5
d    6.0
dtype: float64
"""

注意:①数据支持多种数据类型 ②数据类型可被强制改变

2、用一维numpy数组创建

import numpy as np
import pandas as pd

x = np.arange(5)
pd.Series(x)

3、用字典创建

  • 默认以键为index,值为data:pd.Series(dict)
import pandas as pd

poplation_dict = {"BeiJing": 1234,
                  "ShangHai": 2424,
                  "ShenZhen": 1303,
                  "HangZhou": 981}
pop1 = pd.Series(poplation_dict)
print(pop1)
"""
BeiJing     1234
ShangHai    2424
ShenZhen    1303
dtype: int64
"""
pop2 = pd.Series(poplation_dict, index=["BeiJing", "HangZhou", "c", "d"])
print(pop2)
"""
BeiJing     1234.0
HangZhou     981.0
c              NaN
d              NaN
dtype: float64
"""

字典创建时,如果指定index,则会到字典的键中筛选,找不到的,值则为NaN

4、data为标量

import pandas as pd

p = pd.Series(5, index=[100, 200, 300])
print(p)
"""
100    5
200    5
300    5
dtype: int64
"""

Pandas DataFrame对象

DataFrame是带标签数据的多维数组

DataFrame对象的创建

通用结构:pd.DataFrame(data, index=index, columns=columns)

  • data:数据,可以为列表、字典或Numpy数组
  • index:索引,为可选参数
  • columns:列标签,为可选参数

1、通过Series对象创建

import pandas as pd

poplation_dict = {"BeiJing": 1234,
                  "ShangHai": 2424,
                  "ShenZhen": 1303,
                  "HangZhou": 981}
pop = pd.Series(poplation_dict)
p = pd.DataFrame(pop)
print(p)
"""
             0
BeiJing   1234
ShangHai  2424
ShenZhen  1303
HangZhou   981
"""
p = pd.DataFrame(pop, columns=["population"])
print(p)
"""
          population
BeiJing         1234
ShangHai        2424
ShenZhen        1303
HangZhou         981
"""

2、通过Series对象字典创建

注意:数量不够的会自动补齐

import pandas as pd

poplation_dict = {"BeiJing": 1234,
                  "ShangHai": 2424,
                  "ShenZhen": 1303,
                  "HangZhou": 981}
GDP_dict = {"BeiJing": 1334,
            "ShangHai": 3424,
            "ShenZhen": 5303,
            "HangZhou": 9681}
pop = pd.Series(poplation_dict)
gdp = pd.Series(GDP_dict)
p = pd.DataFrame({"population": pop,
                  "GDP": gdp,
                "country": "china"})
print(p)
"""
                population   GDP country
BeiJing         1234  1334   China
ShangHai        2424  3424   China
ShenZhen        1303  5303   China
HangZhou         981  9681   China
"""

3、通过字典列表对象创建

  • 字典索引作为index,字典键作为columns
  • 不存在的键,会默认为NaN
import pandas as pd

data = [{"a": i, "b": 2*i} for i in range(3)]
p = pd.DataFrame(data)

d1 = [{"a": 1, "b": 1}, {"b": 3, "c": 4}]
p1 = pd.DataFrame(d1)
print(p)
print(p1)
"""
a  b
0  0  0
1  1  2
2  2  4
     a  b    c
0  1.0  1  NaN
1  NaN  3  4.0
"""

4、通过Numpy二维数组创建

import numpy as np
import pandas as pd

p = pd.DataFrame(np.random.randint(10, size=(3, 2)), columns=["foo", "bat"], index=["a", "b", "c"])
print(p)
"""
foo  bat
a    1    3
b    0    3
c    4    6
"""

DataFrame性质

1、属性

  • df.values :返回numpy数组表示的数据
  • df.index:返回行索引
  • df.columns:返回行索引
  • df.shape:形状
  • pd.size:大小
  • pd.dtypes:返回每列数据类型

2、索引

(1) 获取列

  • 字典式:data["列名"]
  • 对象属性式:data.列名

(2) 获取行

  • 绝对索引:df.loc["index名"]
  • 相对索引:df.loc[index名所对应的索引]

(3) 获取标量:df.loc["index名", "列名"]

(4) Series对象的索引:Series对象名["index名"]

3、切片

import numpy as np
import pandas as pd

dates = pd.date_range(start="2019-01-01", periods=6)
print(dates)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=["A", "B", "C", "D"])
print(df)
"""
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
               '2019-01-05', '2019-01-06'],
              dtype='datetime64[ns]', freq='D')
              
                   A         B         C         D
2019-01-01  0.650976  0.195642  0.373875  0.577994
2019-01-02  1.668273 -0.437919  0.107213  2.076671
2019-01-03 -0.969602  0.264837 -0.622912 -1.233762
2019-01-04  0.893448 -0.361137 -2.014520  0.418288
2019-01-05 -1.844135 -0.933371  0.412862 -1.228276
2019-01-06 -0.406997 -0.447221  2.063793 -0.914721
"""

(1) 行切片

print(df["2019-01-01": "2019-01-03"])
print(df.loc["2019-01-01": "2019-01-03"])
print(df.loc[0: 3])    # 相对索引,取0,1,2
"""
                   A         B         C         D
2019-01-01  0.708338 -0.534477  0.409186 -1.046577
2019-01-02 -0.425397  0.050827 -1.136897 -0.120209
2019-01-03  0.191192  0.862435  0.928217  1.448118
                   A         B         C         D
2019-01-01  0.708338 -0.534477  0.409186 -1.046577
2019-01-02 -0.425397  0.050827 -1.136897 -0.120209
2019-01-03  0.191192  0.862435  0.928217  1.448118
"""

(2) 列切片

print(df.loc[:, "A": "C"])
print(df.iloc[:, 0: 3])
"""
                   A         B         C
2019-01-01 -2.569867  0.021640  0.727239
2019-01-02  0.758475  0.209617  0.941152
2019-01-03  0.002097 -0.765052 -0.901855
2019-01-04 -0.209430  0.825318 -0.334309
2019-01-05  0.522325 -2.312552 -0.384917
2019-01-06  1.301911 -0.833983  0.874232
                   A         B         C
2019-01-01 -2.569867  0.021640  0.727239
2019-01-02  0.758475  0.209617  0.941152
2019-01-03  0.002097 -0.765052 -0.901855
2019-01-04 -0.209430  0.825318 -0.334309
"""

(3) 多种多样的取值

  • 行、列同时切片:df.loc["2019-01-02": "2019-01-03", "C": "D"]
  • 行切片、列分散取值:df.loc["2019-01-04": "2019-01-06", ["A", "C"]]
  • 行分散取值、列切片:行分散只能用相对的位置索引进行切片——df.iloc[[1, 5], 0: 3]
  • 行、列均分散取值:也只能用相对位置

4、布尔索引——掩码操作

  • isin():查询每一行对应列的值是否符合——df["E"].isin(["two", "four"])

5、赋值

import pandas as pd
import numpy as np

dates = pd.date_range(start="2019-01-01", periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=["A", "B", "C", "D"])
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range("20190101", periods=6))
df["E"] = s1
print(df)   # 增加新列
"""
 A         B         C         D  E
2019-01-01 -0.658733  0.811131 -0.407930  0.176017  1
2019-01-02  1.221720 -1.436906  1.385231 -2.073760  2
2019-01-03  0.337256  0.878561  0.871931  0.816829  3
2019-01-04  0.656371  0.801415 -0.387575 -1.179588  4
2019-01-05 -0.936013  0.892519 -0.073850  0.983318  5
2019-01-06 -1.084148  0.178440 -1.661800  1.042642  6
"""
df.loc["2019-01-01", "A"] = 0   # 等价于df.iloc[0, 1] = 1,修改赋值
# df["D"] = np.array[5]*len(df)   # 可简化为df["D"] = 5
print(df)
"""
A         B         C         D  E
2019-01-01  0.000000 -0.781050  2.360735 -1.409223  1
2019-01-02  0.390676 -1.364522 -0.678399 -0.653149  2
2019-01-03  0.254998  0.402109  0.982087 -1.918915  3
2019-01-04 -1.498213  0.777009 -1.382488 -0.586266  4
2019-01-05  0.167791 -0.642785 -2.081390 -0.532108  5
2019-01-06  0.463543 -1.630412 -1.603518  1.018081  6
"""
"""修改index和columns"""
df.index = [i for i in range(len(df))]
df.columns = [i for i in range(df.shape[1])]
print(df)
"""
  0         1         2         3  4
0  0.000000 -1.111451  1.206426 -1.584109  1
1 -0.971625 -0.399996  0.311155 -0.713528  2
2 -1.085063  0.020041 -0.300341  0.804175  3
3 -0.426142  0.061551 -0.620271 -0.003336  4
4 -1.501278 -0.134365 -0.384964 -0.502363  5
5  0.648978  0.896500 -1.167059  0.589095  6
"""

数值运算及统计分析

数据的查看

import pandas as pd
import numpy as np

dates = pd.date_range(start="2019-01-01", periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=["A", "B", "C", "D"])
"""查看前面的行"""
df.head()   # 默认5行
df.head(2)
"""查看后面的行"""
df.tail()   # 默认5行
df.tail(3)
"""查看总体信息"""
df.info()

Numpy通用函数同样适用于Pandas

  • (1) 向量化运算
  • (2) 矩阵化运算
  • (3) 广播运算:①按行广播 ②按列广播

3、新的用法

(1) 索引对齐

  • pandas会自动对齐两个的索引,没有的值用np.nan表示
  • 缺省值也可用fill_value来填充:a.add(B, fill_value=0)——直接用运算符,不能填充Nan处

(2) 统计相关

  • 数据种类统计

一般来说,纯粹的计算在Numpy里执行的更快:Numpy更侧重在于计算,Pandas侧重于数据处理

import pandas as pd
import numpy as np
from collections import Counter

y = np.random.randint(3, size=20)
print(y)
"""
[0 1 0 1 2 1 2 0 2 1 2 1 0 2 1 0 0 1 1 1]
"""
print(np.unique(y))
"""
[0 1 2]
"""
print(Counter(y))
"""
Counter({1: 9, 0: 6, 2: 5})
"""
y1 = pd.DataFrame(y, columns=["A"])
print(y1)
"""
    A
0   0
1   0
2   2
3   1
4   0
5   0
6   1
7   1
8   0
9   2
10  0
11  2
12  0
13  0
14  2
15  2
16  0
17  1
18  2
19  0
"""
print(np.unique(y1))    # [0 1 2]
print(y1["A"].value_counts())   
"""
2    10
0     7
1     3
Name: A, dtype: int64
"""
  • 产生新的结果,并进行排序:① city_info.sort_values(by="per_GDP") ① city_info.sort_values(by="per_GDP", ascending=False)
  • 行排序:data.sort_index()
  • 列排序:data.sort_index(axis=1, ascending=False)
  • 非空个数 :df.count()
  • 求和:df.sum() df.sum(axis=1)
  • 最小值、最大值:df.min() df.max(axis=1) df.idxmax()#坐标
  • 均值:df.mean() df.var()
  • 中位数:df.median()
  • 标准差:df.std()
  • 众数:data.mode()
  • 75%分位数:df.quantile(0.75)
  • 一网打尽:df.describe()
  • 相关性系数和协方差:① df.corr() ②df.corrwith(df["A"]) # 某一列的相关信息
  • 自定义输出:apply(method)——使用method方法默认对每一列进行相应的操作
df.apply(lambda x: x.max()-x.min())

缺失值处理

  • 1、发现缺失值:有None、字符串等,数据类型全部变为object,它比int和float更消耗资源
    注意:np.nan是一种特殊的浮点数
  • 2、删除缺失值:①删除整行:data.dropna() ②删除整列:data.dropna(axis="columns", how="all | any")
  • 3、填充缺失值:①用均值进行替换:data.fillna(value=5) ②用均值进行替换:data.fillna(value=data.mean())

合并数据

import pandas as pd

"""构造一个生产DataFrame函数"""
def make_df(cols, ind):
    data = {c: [str(c)+str(i) for i in ind] for c in cols}
    return pd.DataFrame(data, ind)

df_1 = make_df("AB", [1, 2])
df_2 = make_df("AB", [3, 4])
print(df_1)
print(df_2)
"""
 A   B
1  A1  B1
2  A2  B2
    A   B
3  A3  B3
4  A4  B4
"""
"""垂直合并"""
pd_v = pd.concat([df_1, df_2])
print(pd_v)
"""
A   B
1  A1  B1
2  A2  B2
3  A3  B3
4  A4  B4
"""
"""水平合并"""
df_3 = make_df("CD", [1, 2])
pd_h = pd.concat([df_1, df_3], axis=1)
print(pd_h)
"""
    A   B   C   D
1  A1  B1  C1  D1
2  A2  B2  C2  D2
"""
"""行重叠"""
df_5 = make_df("AB", [1, 2])
df_6 = make_df("AB", [1, 2])
print(pd.concat([df_5, df_6], ignore_index=True))
"""
A   B
0  A1  B1
1  A2  B2
2  A1  B1
3  A2  B2
"""
"""对齐合并merge()"""
df_9 = make_df("AB", [1, 2])
df_10 = make_df("BC", [1, 2])
print(pd.merge(df_9, df_10))
"""
  A   B   C
0  A1  B1  C1
1  A2  B2  C2
"""

分组和数据透视表

(1) 分组

  • 延迟计算:df.groupby("key") df.groupby("key").sum()
for i in df.groupby("key"):
    print(str(i))
  • 按列取值: df.groupby("key")["data2"].sum()
  • 按组迭代
for data, group in df.groupby("key"):
    print("{0:5} shape={1}".format(data, group.shape))
  • 过滤:df.groupby("key").filter(filter_func)
  • 转换:df.groupby("key").transform(lambda x: x-x.mean())
  • apply():
  • 用字典将索引映射到分组
    [[]]:dataframe类型
    []:Series类型

数据透视表:数据集.pivot_table("需要查询列的名", index="index名", columns="class")

其他

  • (1) 向量化字符串操作
  • (2) 处理时间序列
  • (3) 多级索引:用于多维数据
    高性能的Pandas:eval()

减少了复合代数式在计算中间过程的内存分配
高性能的Pandas:query()
当处理小数组时,普通方法反而更快


posted @ 2020-02-09 23:45  雪隐lys  阅读(433)  评论(0编辑  收藏  举报