数据分析(Pandas模块:表计算与数据分析)

注意:在pandas中,axis=1表示横坐标,axis=0表示纵坐标。特殊:drop和take函数坐标则相反!!!

一、pandas简单介绍

  1、pandas是一个强大的Python数据分析的工具包。
  2、pandas是基于NumPy构建的。

  3、pandas的主要功能

    • 具备对其功能的数据结构DataFrame、Series
    • 集成时间序列功能
    • 提供丰富的数学运算和操作
    • 灵活处理缺失数据

二、pandas安装

# 安装方法:
pip install pandas

# 导包
import pandas as pd
from pandas import Series,DataFrame

三、Series创建

  Series是一种类似于一位数组的对象,由一组数据和一组与之相关的数据标签(索引)组成。

两种创建方式:

由列表创建

默认索引为0到N-1的整数型索引
通过numpy数组创建

# 使用列表创建Series
Series(data=[1,2,3])
#结果
>>>
0    1
1    2
2    3
dtype: int64

# 还可以通过设置index参数指定索引
s = Series(data=[1,2,3], index=["a","b","c"])
#结果
>>>
a    1
b    2
c    3
dtype: int64

# 通过nunpy数组创建
Series(data=np.random.randint(0,100,size=(3,)))
# 结果
>>>
0    49
1    85
2    11
dtype: int32

# 查看索引"c"的行
s["c"]
#结果
3

四、Series支持数组的特性

  • 从ndarray创建Series:Series(arr)
  • 与标量运算:sr*2
  • 两个Series运算:sr1+sr2
  • 索引:sr[0], sr[[1,2,4]]
  • 切片:sr[0:2](切片依然是视图形式)
  • 通用函数:np.abs(sr)
  • 布尔值过滤:sr[sr>0]

  4.1 使用s.head(),tail()分别查看前n个和后n个值:

# 实验准备:
s = Series(data=[1,2,3], index=["a","b","c"])
# 结果
>>>
a    1
b    2
c    3
dtype: int64

# 查看前2个值
s.head(2)  # s.head()默认查看5个
# 结果
>>>
a    1
b    2
dtype: int64

# 查看最后2个值
s.tail(2)
#结果
>>>
b    2
c    3
dtype: int64

  4.2 对Series元素进行去重:

s = Series(data=[1,1,2,2,3,4,5,6,6,6,7,6,6,7,8])
s.unique()

#结果:
>>>array([1, 2, 3, 4, 5, 6, 7, 8], dtype=int64)

五、Series的统计函数:

  • mean() #求平均数
  • sum() #求和
  • cumsum() #累加

  

六、Series支持字典的特性(标签)

  • 从字典创建Series:Series(dic),
  • in运算:’a’ in sr、for x in sr
  • 键索引:sr['a'], sr[['a', 'b', 'd']]
  • 键切片:sr['a':'c']
  • 其他函数:get('a', default=0)等
In [12]: s = pd.Series(0,index=['a','b','c','d'])

In [13]: s.a
Out[13]: 0

In [14]: v = pd.Series({'a':1,'b':2})

In [15]: v.a
Out[15]: 1

In [16]: v.b
Out[16]: 2

In [17]: v[0]
Out[17]: 1

In [18]: s*2
Out[18]:
a    0
b    0
c    0
d    0
dtype: int64

In [19]: v*2
Out[19]:
a    2
b    4
dtype: int64

七、Series的整数索引

整数索引的pandas对象往往会使新手抓狂。
例:

    • sr = np.Series(np.arange(4.))
    • sr[-1]

如果索引是整数类型,则根据整数进行数据操作时总是面向标签的。

  • loc属性 以标签解释
  • iloc属性 以下标解释

八、Series数据对齐

pandas在运算时,会按索引进行对齐然后计算。如果存在不同的索引,则结果的索引是两个操作数索引的并集。

    例:
    sr1 = pd.Series([12,23,34], index=['c','a','d'])
    sr2 = pd.Series([11,20,10], index=['d','c','a',])
    sr1+sr2
    sr3 = pd.Series([11,20,10,14], index=['d','c','a','b'])
    sr1+sr3

    如何在两个Series对象相加时将缺失值设为0?
    sr1.add(sr2, fill_value=0)
    灵活的算术方法:add, sub, div, mul


使得两个Series进行相加:
  • 当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
  • 在运算中自动对齐不同索引的数据,如果索引不对应,则补NaN

# 两个Series进行相加
s1 = Series(data=[1,2,3,4],index=['a','b','c','d'])
s2 = Series(data=[1,2,3,4],index=['a','b','e','d'])
s = s1 + s2

#结果:

>>>

a    2.0
b    4.0
c    NaN
d    8.0
e    NaN
dtype: float64

九、Series缺失数据

1、缺失数据:使用NaN(Not a Number)来表示缺失数据。其值等于np.nan。内置的None值也会被当做NaN处理。
2、处理缺失数据的相关方法:

    • dropna() 过滤掉值为NaN的行
    • fillna() 填充缺失数据
    • isnull() 返回布尔数组,缺失值对应为True
    • notnull() 返回布尔数组,缺失值对应为False

3、过滤缺失数据:sr.dropna() 或 sr[data.notnull()]
4、填充缺失数据:fillna(0)

# 检测不为空则返回True
s.notnull()
#结果:
>>>a     True
b     True
c    False
d     True
e    False
dtype: bool

# 检测为空则返回True,与notnull用法相反
s.isnull()
#结果
>>>a    False
b    False
c     True
d    False
e     True
dtype: bool

# 如果将布尔值作为Serrise的索引,则只保留True对应的元素值
s[[True,True,False,False,True]]
#结果
>>>a    2.0
b    4.0
e    NaN
dtype: float64

# 索引为True返回
s[s.notnull()]
#结果
>>>a    2.0
b    4.0
d    8.0
dtype: float64

十、DataFrame创建

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

DataFrame的创建 最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。

此外,DataFrame会自动加上每一行的索引。

使用字典创建的DataFrame后,则columns参数将不可被使用。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

 

DataFrame是一个表格型的数据结构,含有一组有序的列。
DataFrame可以被看做是由Series组成的字典,并且共用一个索引。

创建方式:

pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']), 'two':pd.Series([1,2,3,4],index=['b','a','c','d'])})
……
csv文件读取与写入:

df.read_csv('E:\算法\day110 Numpy、Pandas模块\601318.csv')
df.to_csv()

  10.1 创建DataFrame:

# 方式一:通过字典创建DataFrame
dic = {
    '张三':[150,150,150,150],
    '李四':[0,0,0,0]
}
df = DataFrame(data=dic,index=['语文','数学','英语','理综'])
#结果
>>>    张三    李四
语文    150    0
数学    150    0
英语    150    0
理综    150    0

# 方式二:创建DataFrame
DataFrame(data=np.random.randint(60,100,size=(3,4)))
#结果
>>>    0    1    2    3
0    70    63    66    89
1    80    79    94    79
2    86    83    63    79

# 创建DataFrame,并指定行索引(index)与列索引(columns)
df = DataFrame(data=np.random.randint(60,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d'])
#结果:
>>>    a    b    c    d
A    65    93    91    91
B    70    82    65    96
C    72    93    81    77

十、DataFrame查看数据

查看数据常用属性及方法:
        index                    获取索引
        T                        转置
        columns                    获取列索引
        values                    获取值数组
        describe()                获取快速统计

    DataFrame各列name属性:列名
    rename(columns={})

 

# DataFrame的values属性
df.values
#结果:
>>>array([[65, 93, 91, 91],
       [70, 82, 65, 96],
       [72, 93, 81, 77]])

# DataFrame的index属性
df.index
#结果
>>>Index(['A', 'B', 'C'], dtype='object')

# DataFrame的columns属性
df.columns
#结果
>>>Index(['a', 'b', 'c', 'd'], dtype='object')

十一、DataFrame索引和切片

1、DataFrame有行索引和列索引。
2、DataFrame同样可以通过标签和位置两种方法进行索引和切片。

3、DataFrame使用索引切片:

    • 方法1:两个中括号,先取列再取行。 df['A'][0]
    • 方法2(推荐):使用loc/iloc属性,一个中括号,逗号隔开,先取行再取列。

loc属性:解释为标签
iloc属性:解释为下标
向DataFrame对象中写入值时只使用方法2
行/列索引部分可以是常规索引、切片、布尔值索引、花式索引任意搭配。(注意:两部分都是花式索引时结果可能与预料的不同)

通过标签获取:
    df['A']
    df[['A', 'B']]
    df['A'][0]
    df[0:10][['A', 'C']]
    df.loc[:,['A','B']]  #行是所有的行,列取是A和B的
    df.loc[:,'A':'C']
    df.loc[0,'A']
    df.loc[0:10,['A','C']]
    
通过位置获取:
    df.iloc[3]
    df.iloc[3,3]
    df.iloc[0:3,4:6]
    df.iloc[1:5,:]
    df.iloc[[1,2,4],[0,3]]、
    
通过布尔值过滤:

  df[df['A']>0]
  df[df['A'].isin([1,3,5])]
  df[df<0] = 0

  11.1 对列进行索引:

# 可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名
df = DataFrame(data=np.random.randint(60,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d'])
#结果:
>>>  a    b    c    d
A    73    73    83    79
B    67    76    63    69
C    86    77    79    82

#修改列索引
df.columns = ['a','c','b','d']
#结果
>>>  a    c    b    d
A    73    73    83    79
B    67    76    63    69
C    86    77    79    82

# 获取前两列
df[["a","c"]]
#结果
>>>a    c
A    73    73
B    67    76
C    86    77

  11.2 对行进行索引:

# 通过隐式索引取值(iloc)
df.iloc[0]
#结果
>>>a    73
c    73
b    83
d    79
Name: A, dtype: int32

# 通过显示索引取值(loc)
df.loc["A"]
#结果
>>>a    73
c    73
b    83
d    79
Name: A, dtype: int32

# 通过索引获取多个值,获取行
df.loc[["A", "B"]]
#结果:
>>>
    a    c    b    d
A    73    73    83    79
B    67    76    63    69

# 获取某一个值,第二行第三个值
df.iloc[1,2]
#结果
>>>63

# 索引获取多个值(行索引在前,列索引在后)
df.loc[["B","C"],"b"]
#结果
>>>B    63
C    79
Name: b, dtype: int32

  11.3 DataFrame切片操作:

DataFrame切片操作
    索引表示的是列索引
    切片表示的是行切片

#实验准备
print(df)
#结果:
>>>
     a    c    b    d
A    73    73    83    79
B    67    76    63    69
C    86    77    79    82    

# 获取前2行
df[0:2]
#结果
     a    c    b    d
A    73    73    83    79
B    67    76    63    69            

# 获取前2列
df.iloc[:,0:2]
#结果
>>>a    c
A    73    73
B    67    76
C    86    77

  11.4 DataFrame的运算:

DataFrame之间的运算同Series一样:

    在运算中自动对齐不同索引的数据
    如果索引不对应,则补NaN


# DataFrame的相加运算
df + df
#结果:
>>>a    c    b    d
A    146    146    166    158
B    134    152    126    138
C    172    154    158    164

十二、DataFrame数据对齐与缺失数据

DataFrame对象在运算时,同样会进行数据对齐,行索引与列索引分别对齐。
结果的行索引与列索引分别为两个操作数的行索引与列索引的并集。

DataFrame处理缺失数据的相关方法:

    • dropna(axis=0,where=‘any’,…) 过滤掉值为NaN的行
    • fillna() 填充缺失数据
    • isnull() 返回布尔数组,缺失值对应为True
    • notnull() 返回布尔数组,缺失值对应为False

  12.1 pandas中None与np.nan的数据类型:

None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。
pandas中None与np.nan都视作np.nan

# 查看None的数据类型
type(None)
#结果
>>>NoneType

# 查看np.nan的数据类型,nan:浮点类型
type(np.nan)
#结果
>>>float

# np.nan不能做运算.因为np.nan运算没有意义,返回结果还是nan
np.nan + 1
#结果
>>>nan

  12.2 pandas中的空值处理:

  • isnull():判断空值则为True
  • notnull():判断非空值则为True
  • drop():过滤丢失数据
  • fillna():填充丢失数据
#数据准备:
# 创建DataFrame
df = DataFrame(data=np.random.randint(0,100,size=(13,9)))
#将某些数组元素赋值为nan
df.iloc[2,4] = None
df.iloc[5,5] = np.nan
df.iloc[2,2] = None
df.iloc[7,3] = None
df.iloc[6,8] = None
df
#结果>>>
      0     1     2       3       4       5       6     7     8
0     36    50    69.0    47.0    92.0    22.0    35    26    20.0
1     25    9     78.0    51.0    66.0    44.0    87    44    96.0
2     21    37    NaN     28.0    NaN     46.0    58    9     22.0
3     64    37    66.0    61.0    40.0    9.0     33    34    18.0
4     53    11    46.0    31.0    77.0    79.0    68    17    8.0
5     14    61    99.0    59.0    63.0    NaN     10    40    74.0
6     94    65    29.0    75.0    53.0    16.0    11    64    NaN
7     43    80    79.0    NaN     88.0    64.0    26    11    1.0
8     24    95    36.0    37.0    84.0    28.0    79    69    39.0
9     22    95    3.0     99.0    16.0    77.0    91    39    80.0
10    85    44    40.0    17.0    68.0    52.0    98    13    82.0
11    53    39    96.0    24.0    32.0    84.0    57    8     30.0
12    47    9     85.0    88.0    58.0    57.0    15    25    94.0    


# 判断空值项返回True,否则返回False
df.isnull()
#结果>>>
      0        1        2        3        4        5        6        7        8
0     False    False    False    False    False    False    False    False    False
1     False    False    False    False    False    False    False    False    False
2     False    False    True     False    True     False    False    False    False
3     False    False    False    False    False    False    False    False    False
4     False    False    False    False    False    False    False    False    False
5     False    False    False    False    False    True     False    False    False
6     False    False    False    False    False    False    False    False    True
7     False    False    False    True     False    False    False    False    False
8     False    False    False    False    False    False    False    False    False
9     False    False    False    False    False    False    False    False    False
10    False    False    False    False    False    False    False    False    False
11    False    False    False    False    False    False    False    False    False
12    False    False    False    False    False    False    False    False    False


# 判断空值项返回False,否则返回True
df.notnull()
#结果>>>
      0       1       2       3       4       5       6       7       8
0     True    True    True    True    True    True    True    True    True
1     True    True    True    True    True    True    True    True    True
2     True    True    False   True    False   True    True    True    True
3     True    True    True    True    True    True    True    True    True
4     True    True    True    True    True    True    True    True    True
5     True    True    True    True    True    False   True    True    True
6     True    True    True    True    True    True    True    True    False
7     True    True    True    False   True    True    True    True    True
8     True    True    True    True    True    True    True    True    True
9     True    True    True    True    True    True    True    True    True
10    True    True    True    True    True    True    True    True    True
11    True    True    True    True    True    True    True    True    True
12    True    True    True    True    True    True    True    True    True

# any:指定行或者列,isnull + any 有True(空)则返回本行为True
df.isnull().any(axis=1)
#结果>>>
0     False
1     False
2      True
3     False
4     False
5      True
6      True
7      True
8     False
9     False
10    False
11    False
12    False
dtype: bool

# all:指定行或者列,notnull + all 本行所有True(非空)则返回本行为True
df.notnull().all(axis=1)
#结果>>>
0      True
1      True
2     False
3      True
4      True
5     False
6     False
7     False
8      True
9      True
10     True
11     True
12     True
dtype: bool

# 去除空行,保留所有非空行数据
df.loc[df.notnull().all(axis=1)]
#结果>>>
      0     1     2       3       4       5       6     7     8
0     36    50    69.0    47.0    92.0    22.0    35    26    20.0
1     25    9     78.0    51.0    66.0    44.0    87    44    96.0
3     64    37    66.0    61.0    40.0    9.0     33    34    18.0
4     53    11    46.0    31.0    77.0    79.0    68    17    8.0
8     24    95    36.0    37.0    84.0    28.0    79    69    39.0
9     22    95    3.0     99.0    16.0    77.0    91    39    80.0
10    85    44    40.0    17.0    68.0    52.0    98    13    82.0
11    53    39    96.0    24.0    32.0    84.0    57    8     30.0
12    47    9     85.0    88.0    58.0    57.0    15    25    94.0

# df.dropna() 过滤空值,保留没有空值的行或者列
# df.dropna() 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列
df.dropna(axis=0)
#结果>>>
      0     1     2       3       4       5       6     7     8
0     36    50    69.0    47.0    92.0    22.0    35    26    20.0
1     25    9     78.0    51.0    66.0    44.0    87    44    96.0
3     64    37    66.0    61.0    40.0    9.0     33    34    18.0
4     53    11    46.0    31.0    77.0    79.0    68    17    8.0
8     24    95    36.0    37.0    84.0    28.0    79    69    39.0
9     22    95    3.0     99.0    16.0    77.0    91    39    80.0
10    85    44    40.0    17.0    68.0    52.0    98    13    82.0
11    53    39    96.0    24.0    32.0    84.0    57    8     30.0
12    47    9     85.0    88.0    58.0    57.0    15    25    94.0

# fillna():value和method参数
# fillna() 填充函数 ffill:填充上一行对应的值,bfill:填充下一行对应的值
df.fillna(method="ffill", axis=1)
#结果>>>
      0       1       2       3       4       5       6       7       8
0     36.0    50.0    69.0    47.0    92.0    22.0    35.0    26.0    20.0
1     25.0    9.0     78.0    51.0    66.0    44.0    87.0    44.0    96.0
2     21.0    37.0    37.0    28.0    28.0    46.0    58.0    9.0     22.0
3     64.0    37.0    66.0    61.0    40.0    9.0     33.0    34.0    18.0
4     53.0    11.0    46.0    31.0    77.0    79.0    68.0    17.0    8.0
5     14.0    61.0    99.0    59.0    63.0    63.0    10.0    40.0    74.0
6     94.0    65.0    29.0    75.0    53.0    16.0    11.0    64.0    64.0
7     43.0    80.0    79.0    79.0    88.0    64.0    26.0    11.0    1.0
8     24.0    95.0    36.0    37.0    84.0    28.0    79.0    69.0    39.0
9     22.0    95.0    3.0     99.0    16.0    77.0    91.0    39.0    80.0
10    85.0    44.0    40.0    17.0    68.0    52.0    98.0    13.0    82.0
11    53.0    39.0    96.0    24.0    32.0    84.0    57.0    8.0     30.0
12    47.0    9.0     85.0    88.0    58.0    57.0    15.0    25.0    94.0

十三、pandas:其他常用方法(concat,merge)

- mean        #求平均值
- sum         #求和
- sort_index  #按行或列索引排序
- sort_values  #按值排序
- apply(func,axis=0)  #axis=0指的是逐行,axis=1指的是逐列。
        df.apply(lamada x:x.mean())  #按列求平均
        df.apply(lamada x:x['high']+x["low"])/2,axis=1)  #按列求平均(最高价和最低价的平均)
        df.apply(lamada x:x['high']+x["low"])/2,axis=1)  #按列求平均(最高价和最低价的平均)
- applymap(func) #将函数应用在DataFrame各个元素上
- map(func) #将函数应用在Series各个元素上
pandas的拼接分为两种:

    - 级联:pd.concat, pd.append
    - 合并:pd.merge, pd.join

  13.1 使用pd.concat()级联:

pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
    - pd.concat参数:
        objs
        axis=0
        keys
        join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
ignore_index=False        

# 实验准备:准备数据
df1 = DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d'])
df2 = DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['A','D','C'],columns=['a','b','e','d'])
# 显示数据
display(df1,df2)
#结果>>>
     a     b     c     d
A    23    26    89    16
B    12    82    41    15
C    99    72    72    3
     a     b     e     d
A    67    76    43    82
D    68    71    77    3
C    73    6     41    37


# 匹配的级联(数据格式(index与columns)相同)
pd.concat((df1,df1,df1),axis=1,join="inner")
#结果:>>>
     a     b     c     d     a     b     c     d     a     b     c     d
A    23    26    89    16    23    26    89    16    23    26    89    16
B    12    82    41    15    12    82    41    15    12    82    41    15
C    99    72    72    3     99    72    72    3     99    72    72    3


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

    外连接:补NaN(默认模式)
    内连接:只连接匹配的项

pd.concat((df1,df2),axis=0,join="inner")
#结果:>>>
     a    b    d
A    23    26    16
B    12    82    15
C    99    72    3
A    67    76    82
D    68    71    3
C    73    6     37

  13.2 使用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],
                })
display(df1,df2)
#结果:>>>
     employee     group
0    Bob        Accounting
1    Jake        Engineering
2    Lisa        Engineering
     employee     hire_date
0    Lisa        2004
1    Bob          2008
2    Jake        2012

# 一对一合并
pd.merge(df1,df2)
#结果>>>
     employee    group        hire_date
0    Bob       Accounting    2008
1    Jake      Engineering    2012
2    Lisa      Engineering    2004


# 数据准备:创建df3,df4
df3 = DataFrame({
    'employee':['Lisa','Jake'],
    'group':['Accounting','Engineering'],
    'hire_date':[2004,2016]})
df4 = DataFrame({'group':['Accounting','Engineering','Engineering'],
                       'supervisor':['Carly','Guido','Steve']
                })
display(df3,df4)
# 结果>>>
   employee      group          hire_date
0    Lisa         Accounting     2004
1    Jake         Engineering    2016
    group          supervisor
0    Accounting     Carly
1    Engineering    Guido
2    Engineering    Steve

# 多对一合并
pd.merge(df3,df4)
#结果>>>
    employee  group        hire_date    supervisor
0    Lisa    Accounting     2004         Carly
1    Jake    Engineering    2016        Guido
2    Jake    Engineering    2016        Steve

# 数据准备:创建df5,df6
df5 = DataFrame({'employee':['Bob','Jake','Lisa'],
                 'group':['Accounting','Engineering','Engineering']})
df6 = DataFrame({'group':['Engineering','Engineering','HR'],
                'supervisor':['Carly','Guido','Steve']
                })
display(df5,df6)
#结果>>>
    employee      group
0    Bob         Accounting
1    Jake        Engineering
2    Lisa        Engineering
    group          supervisor
0    Engineering    Carly
1    Engineering    Guido
2    HR             Steve

# merge外连接
pd.merge(df5,df6,how="outer")
#结果>>>
     employee  group        supervisor
0    Bob     Accounting     NaN
1    Jake    Engineering    Carly
2    Jake    Engineering    Guido
3    Lisa    Engineering    Carly
4    Lisa    Engineering    Guido
5    NaN     HR            Steve

  13.3 key的规范化:

  • 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
  • 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
#数据准备
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']})
display(df1,df2)
#结果>>>
     employee    group
0    Jack       Accounting
1    Summer      Finance
2    Steve      Marketing
     employee    group       hire_date
0    Jack      Accounting    2003
1    Bob       sell        2009
2    Jake      ceo         2012


#多个列名称相同时,需要使用on=来指定哪一个列作为key进行合成
pd.merge(df1,df2,on="employee")
#结果>>>
     employee    group_x      group_y      hire_date
0    Jack       Accounting    Accounting    2003


# 数据准备:
df1 = DataFrame({'employee':['Bobs','Linda','Bill'],
                'group':['Accounting','Product','Marketing'],
               'hire_date':[1998,2017,2018]})
df2 = DataFrame({'name':['Lisa','Bobs','Bill'],
                'hire_dates':[1998,2016,2007]})
display(df1,df2)
#结果>>>
    employee       group        hire_date
0    Bobs        Accounting    1998
1    Linda       Product      2017
2    Bill        Marketing     2018
     hire_dates    name
0    1998         Lisa
1    2016        Bobs
2    2007        Bill

# 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
pd.merge(df1,df2,left_on='employee',right_on='name')
#结果>>>
     employee    group       hire_date    hire_dates     name
0    Bobs       Accounting    1998        2016        Bobs
1    Bill       Marketing     2018        2007        Bill

十四、pandas删除重复数据

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

  • keep参数:指定保留哪一重复的行数据
    • keep="first" 保留第一次重复值
    • keep="last" 保留最后一次重复值
    • keep=False 重复值都不保留
# 实验准备,创建DaraFrame
df = DataFrame(data=np.random.randint(0,100,size=(9,5)))
df.iloc[1] = [6,6,6,6,6]
df.iloc[3] = [6,6,6,6,6]
df.iloc[5] = [6,6,6,6,6]
#结果>>>
     0     1     2     3     4
0    56    27    54    71    71
1    6     6     6     6     6
2    22    57    79    94    31
3    6     6     6     6     6
4    75    16    62    81    91
5    6     6     6     6     6
6    18    38    32    52    10
7    84    50    79    76    69
8    28    14    26    97    33

# 使用drop_duplicates()函数删除重复的行 
# keep="first" 保留第一次重复的行数据
df.drop_duplicates(keep="first")
#结果>>>
     0     1     2     3     4
0    56    27    54    71    71
1    6     6     6     6     6
2    22    57    79    94    31
4    75    16    62    81    91
6    18    38    32    52    10
7    84    50    79    76    69
8    28    14    26    97    33

十五、pandas映射与替换

  15.1 替换元素(replace()):

  • 单值替换
    • 普通替换: 替换所有符合要求的元素: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")
#结果>>>
     0      1      2      3      4
0    56     27     54     71     71
1    six    six    six    six    six
2    22     57     79     94     31
3    six    six    six    six    six
4    75     16     62     81     91
5    six    six    six    six    six
6    18     38     32     52     10
7    84     50     79     76     69
8    28     14     26     97     33

# 通过字典替换:替换所有的6为six
df.replace(to_replace={6:"six"})
#结果
     0      1      2      3      4
0    56     27     54     71     71
1    six    six    six    six    six
2    22     57     79     94     31
3    six    six    six    six    six
4    75     16     62     81     91
5    six    six    six    six    six
6    18     38     32     52     10
7    84     50     79     76     69
8    28     14     26     97     33

# 特殊替换:替换指定列中的数值替换,第三列的所有6替换成six
df.replace(to_replace={3:6},value="six")
#结果>>>
     0     1     2     3      4
0    56    27    54    71     71
1    6     6     6     six    6
2    22    57    79    94     31
3    6     6     6     six    6
4    75    16    62    81     91
5    6     6     6     six    6
6    18    38    32    52     10
7    84    50    79    76     69
8    28    14    26    97     33

  15.2 映射(map()):

  map函数并不是df的方法,而是series的方法:

  • map的几种类型:
    • map()可以映射新一列数据
    • map()中可以使用lambd表达式
    • map()中可以使用方法,可以是自定义的方法
  • 表达式:
    • eg:map({to_replace:value})
  • 注意:

    • map()中不能使用sum之类的函数,for循环
    • 并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数
# 数据准备
dic = {
    'name':['jay','tom','jay'],
    'salary':[9999,5000,9999]
}
df = DataFrame(data=dic)
#结果>>>
     name    salary
0    jay     9999
1    tom     5000
2    jay     9999

# 新增一列:给df中,添加一列,该列的值为中文名对应的英文名
# dic 自定义字段映射表
dic = {
    "jay": "周杰棍",
    "tom": "双杰伦"
}
df["c_name"] = df["name"].map(dic)
#结果>>>
     name    salary    c_name
0    jay     9999      周杰棍
1    tom     5000      双杰伦
2    jay     9999      周杰棍


# map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数)

# 使用自定义函数
def after_sla(s):
    return s - (s-5000)*0.05
    
# 通过map函数计算salary超过5000部分的钱缴纳5%的税
df["after_salary"]= df["salary"].map(after_sla)
# 结果>>>
     name    salary    c_name    after_salary
0    jay     9999      周杰棍     9749.05
1    tom     5000      双杰伦     5000.00
2    jay     9999      周杰棍     9749.05

# 运算工具apply,这里运算结果同上
df["salary"].apply(after_sla)
# 结果>>>
0    9749.05
1    5000.00
2    9749.05
Name: salary, dtype: float64

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

  • 使用df.std()函数可以求得DataFrame对象每一列的标准差
# 实验准备 创建一个1000行3列的df 范围(0-1),求其每一列的标准差
df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
df.head()
#结果:>>>
     A         B        C
0    0.749659    0.205499    0.314041
1    0.828922    0.730040    0.051446
2    0.127467    0.423789    0.768037
3    0.648669    0.301543    0.400714
4    0.963059    0.675478    0.722997

# 需求:对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差
#  获取C列数据大于两倍的C列标准差
std_twice = df["C"].std()*2
std_twice
#结果>>>
0.5683930751229487

# 判断C列数据中,数值大于2倍标准差的数值为异常数值
df["C"] > std_twice
# 获取异常数值行索引
indexs = df.loc[df["C"] > std_twice].index
# 根据索引值,删除异常数据行
df.drop(labels=indexs,axis=0,inplace=True)   //axis=0表示行
df

十七、pandas排序

使用.take()函数排序
在take函数中,axis=1表示纵坐标,axis=0表示横坐标 take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序 eg:df.take([
1,3,4,2,5]) 可以借助np.random.permutation()函数随机排序 # 先对数据列排序,在对行进行随机打乱排序(np.random.permutation(500)) df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0) # 在打乱的DataFrame中随机获取10行 df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0)[0:10] #结果>>>    C     B      A 875 0.410932 0.964015 0.338284 478 0.202094 0.797299 0.981498 114 0.530967 0.510114 0.041500 248 0.517917 0.491662 0.937298 410 0.289813 0.124048 0.659223 562 0.143723 0.476050 0.309460 603 0.418067 0.475892 0.817013 599 0.216818 0.482342 0.141371 480 0.373935 0.725371 0.945609 176 0.510821 0.128612 0.230764

十八、pandas数据分类处理(groupby)

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

数据分类处理:

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

数据分类处理的核心:

 - groupby()函数
 - groups属性查看分组情况
 - 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]})
#结果>>>

     color     item      price     weight
0    red      Apple     4.0      12
1    yellow    Banana    3.0      20
2    yellow    Orange    3.0      50
3    green     Banana    2.5      30
4    green     Orange    4.0      20
5    green     Apple     2.0      44


# 使用groupby实现分组 对item分组,返回一个分组对象
df.groupby(by="item")
#结果>>>
<pandas.core.groupby.DataFrameGroupBy object at 0x000001B31CF8F940>

#groups属性:显示分组情况
df.groupby(by="item").groups
#结果>>>
{'Apple': Int64Index([0, 5], dtype='int64'),
 'Banana': Int64Index([1, 3], dtype='int64'),
 'Orange': Int64Index([2, 4], dtype='int64')}


#方法一:给df创建一个新列,内容为各个水果的平均价格(mean()获取平平均值)
df.groupby(by="item").mean()["price"]
#结果>>>
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64


# 方式二:先获取指定计算的列,效率比方法一高
mean_price_s = df.groupby(by="item")["price"].mean()
mean_price_s
#结果>>>
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64

# to_dict()生层字典
dic = mean_price_s.to_dict()
#结果>>>
{'Apple': 3.0, 'Banana': 2.75, 'Orange': 3.5}

# 添加新列,
df["mean_price"] = df["item"].map(dic)
#结果>>>
     color     item      price     weight    mean_price
0    red      Apple     4.0      12      3.00
1    yellow    Banana    3.0      20      2.75
2    yellow    Orange    3.0      50      3.50
3    green     Banana    2.5      30      2.75
4    green     Orange    4.0      20      3.50
5    green     Apple     2.0      44      3.00

  高级数据聚合:

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

  • df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
# 自定义函数 s为分组后的series数据类型列表
def my_mean(s):
    sum = 0
    for i in s:
        sum += i
    return sum/s.size


# transform用法,返回是映射后的结果值
df.groupby(by="item")["price"].transform(my_mean)
#结果>>>
0    3.00
1    2.75
2    3.50
3    2.75
4    3.50
5    3.00
Name: price, dtype: float64

# apply用法,返回是未被映射后的结果值
df.groupby(by="item")["price"].apply(my_mean)
#结果:>>>
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64

  聚合补充:

分组
   df = pd.DateFrame({
       'data1':np.random.uniform(10,20,5),
       'data2':np.random.uniform(-10,10,5),
       'key1':list("sbbsb")
       'key2':
   })
   df.groupby('key1').mean()  #做平均
   df.groupby('key1').sum()  #做平均
   df.groupby(['key1','key2']).mean()  #做平均  支持分层索引,按多列分组
   
   df.groupby(len).mean()  #传一个函数的时候,x是每一个行的索引
   df.groupby(lambda x:len(x)).mean()  #传一个函数的时候,x是每一个行的索引
   
   df.groupby.groups()  #取得多有的组
   df.groupby.get_group()  #取得一个组
   
聚合
    df.groupby('key1').max()[['data1','data2']]   #去掉key2的data1,data2,花式索引
    df.groupby('key1').max()[['data1','data2']]- df.groupby('key1').min()[['data1','data2']]  #去掉key2
   
   df.groupby('key1').agg(lamada x:x.max()-x.min())
   
   既想看最大也可看最小
    df.groupby('key1').agg([np.max,np.min])
    不同的列不一样的聚合
    df.groupby('key1').agg({'data1':'min','data2':'max'})  #键是列名,值是
    
    a=_219  #219行的代码
    a.resample('3D'),mean()  #3D 3天,3M就是三周
    
数据合并
    - 数据拼接
        df = df.copy()
        pd.concat([df,df2,df3],ignore_index=True)  #不用之前的索引,
        pd.concat([df,df2,df3],axis=1)  #
        pd.concat([df,df2,df3],keys=['a','b','c'])  #不用之前的索引,
        df2.appeng(df3)
    - 数据连接
    如果不指定on,默认是行索引进行join
    pd.merge(df,df3,on='key1')
    pd.merge(df,df3,on='['key1','key2'])

十九、pandas:时间对象处理

时间序列类型:
    时间戳:特定时刻
    固定时期:如2017年7月
    时间间隔:起始时间-结束时间
Python标准库:datetime
    datetime.datetime.timedelta  # 表示 时间间隔
    dt.strftime() #f:format吧时间对象格式化成字符串
    strptime()  #吧字符串解析成时间对象p:parse
    灵活处理时间对象:dateutil包
        dateutil.parser.parse('2018/1/29') 
    成组处理时间对象:pandas
        pd.to_datetime(['2001-01-01', '2002-02-02'])

  产生时间对象数组:date_range

  • start 开始时间
  • end 结束时间
  • periods 时间长度
  • freq 时间频率,默认为'D',可选H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…

二十、pandas:时间序列

1、时间序列就是以时间对象为索引的Series或DataFrame。

2、datetime对象作为索引时是存储在DatetimeIndex对象中的。

3、时间序列特殊功能:

  • 传入“年”或“年月”作为切片方式
  • 传入日期范围作为切片方式
  • 丰富的函数支持:resample(), strftime(), ……
  • 批量转换为datetime对象:to_pydatetime()

二十一、pandas:从文件读取

1、时间序列就是以时间对象作为索引

    • 读取文件:从文件名、URL、文件对象中加载数据
    • read_csv 默认分隔符为csv
    • read_table 默认分隔符为\t
    • read_excel 读取excel文件

2、读取文件函数主要参数:

    • sep 指定分隔符,可用正则表达式如'\s+'
    • header=None 指定文件无列名
    • name 指定列名
    • index_col 指定某列作为索引
    • skip_row 指定跳过某些行
    • na_values 指定某些字符串表示缺失值
    • parse_dates 指定某些列是否被解析为日期,布尔值或列表
df = pd.read_csv("601318.csv")   #默认以,为分隔符
    - pd.read_csv("601318.csv",sep='\s+')  #匹配空格,支持正则表达式
    - pd.read_table("601318.csv",sep=',')  #和df = pd.read_csv("601318.csv")   一样
    - pd.read_excle("601318.xlsx")  #读Excel文件
    sep:指定分隔符
    header = NOne,就会吧默认的表名去除 了
    df.rename(column={0:'a',1:"b"})  #修改列名
    pd.read_csv(index_col=0)  #第0列
    如果想让时间成为索引
        pd.read_csv(index_col='date')  #时间列
    pd.read_csv(index_col='date',parse_datas=True)  #时间列
    parse_datas转换为时间对象,设为true是吧所有能转的都转
    pd.read_csv(index_col='date',parse_datas=['date'])   #知识吧date的那一列转换成时间对象
        
    na_values=['None']  #吧表里面为None的转换成NaN,是吧字符串转换成缺失值
    na_rep()  #是吧缺失值nan转换成字符串

    cols #指定输出的列,传入列表

二十二、pandas:写入到文件

1、写入到文件:

    • to_csv

2、写入文件函数的主要参数:

    • sep
    • na_rep 指定缺失值转换的字符串,默认为空字符串
    • header=False 不输出列名一行
    • index=False 不输出行索引一列
    • cols 指定输出的列,传入列表

3、其他文件类型:json, XML, HTML, 数据库
4、pandas转换为二进制文件格式(pickle):

    • save
    • load

 

posted @ 2019-08-13 21:41  Amorphous  阅读(660)  评论(0编辑  收藏  举报