五、Pandas库(下)

一、数据加载、存储和文件格式

函数说明
read_csv从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为逗号
read_table从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为制表符(“\t”)
read_fwf读取定宽列格式数据(也就是或,没有分隔符)
read_clipboard读取剪贴板中的数据,可以看做 read_table 的剪贴板版。再将网页转换为表格时很有用
read_excel从 Excel XLS 或 XLSX file 读取表格数据
read_hdf读取 pandas 写的 HDF5 文件
read_html读取 HTML 文档中的所有表格
read_json读取JSON(JavaScript Object Notation)字符串中的数据
read_msgpack二进制格式编码的 pandas 数据
read_pickle读取 Python pickle 格式中存储的任意对象
read_sas读取存储于 SAS 系统自定义存储格式的 SAS 数据集
read_sql(使用 SQLAlchemy)读取 SQL 查询结果为 pandas 的 DataFrame
read_stata读取 Stata 文件格式的数据集
参数说明
path表示文件系统位置、URL、文件型对象的字符串
sep或delimiter用于对行中各字段进行拆分的字符序列或正则表达式
header用作列名和行号。默认为0(第一行),如果没有header行就应该设置为None
index_col用作行索引的列编号或列名。可以是单个名称/数字或由多个名称/数字组成的列表(层次化索引)
names用于结果列名列表,结合header=None
skiprows需要忽略的行数(文件开始处算起),或需要跳过的行号列表(从0开始)
na_values一组用于替换NA的值
comment用于将注释信息从行尾拆分出来的字符(一个或多个)
parse_dates尝试将数据解析为日期,默认为False,如果为True,则尝试解析所有列。此外,还可以指定需要解析的一组列好或列名。如果列表的元素为列表或元组,就会将多个列组合到一起再进行日期解析工作(例如,日期/时间分别位于两个列中)
keep_deta_col如果连接多列解析日期,则保持参与连接的列。默认为False
converters由列号/列名跟函数之间的映射关系组成的字典。例如,[‘foo’:f]会对foo列的所有值应用函数f
dayfirst当解析有歧义的日期时,将其看做国际格式(例如,7/6/2012 -> June 7,2012)。默认为False
date_parser用于解析日期的函数
nrows需要读取的行数(从文件开始处算起)
iterator返回一个TextParser以便逐块读取文件
chunksize文件块的大小(用于迭代)
skip_footer需要忽略的函数(从文件末尾处算起)

1.1 读写文本格式文件

1.1.1 读文本的方式

import pandas as pd
import numpy as np
df = pd.read_csv('pandas_test.csv')
print(df,'\n')
   1   2   3   4 message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12  python 

df = pd.read_table('pandas_test.csv',sep=',')
print(df,'\n')
   1   2   3   4 message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12  python 

# 读取时使用默认列索引
df = pd.read_csv('pandas_test.csv',header=None)
print(df,'\n')
   0   1   2   3        4
0  1   2   3   4  message
1  1   2   3   4    hello
2  5   6   7   8    world
3  9  10  11  12   python 

# 读取时设置列索引
# names设置列索引后,会把csv所有数据作为的数据内容
df = pd.read_csv('pandas_test.csv',names=list('abcd')+['message'])
print(df,'\n')
   a   b   c   d  message
0  1   2   3   4  message
1  1   2   3   4    hello
2  5   6   7   8    world
3  9  10  11  12   python 

# index_col参数,设置某一列作为dataframe的行索引
df = pd.read_csv('pandas_test.csv',names=list('abcd')+['message'],index_col='message')
print(df,'\n')
         a   b   c   d
message               
message  1   2   3   4
hello    1   2   3   4
world    5   6   7   8
python   9  10  11  12 

# 设置层次索引
df1 = pd.read_csv('csv_mindex.csv')
print(df1,'\n')

df1 = pd.read_csv('csv_mindex.csv',index_col=['key1','key2'])
print(df1,'\n')
  key1 key2  value1  value2
0  one    a       1       2
1  one    b       3       4
2  one    c       5       6
3  one    d       6       8
4  two    a       9      10
5  two    b      11      12
6  two    c      13      14
7  two    d      15      16 

           value1  value2
key1 key2                
one  a          1       2
     b          3       4
     c          5       6
     d          6       8
two  a          9      10
     b         11      12
     c         13      14
     d         15      16 

# 分块读取大文件
# 设置 chunksize 的大小,会每次读取部分的数据
agg1 = pd.read_csv('csv_mindex.csv',chunksize=1)
print(type(agg1))
<class 'pandas.io.parsers.readers.TextFileReader'>
# 每次执行当前代码会分块读取相关数值
print(agg1.get_chunk())
  key1 key2  value1  value2
0  one    a       1       2
# iterator 设置读取到迭代器对象(只能遍历一次)
agg2 = pd.read_csv('csv_mindex.csv',iterator=True)
print(type(agg2))
<class 'pandas.io.parsers.readers.TextFileReader'>
# 使用 get_chunk 获取指定多个数据
print(agg2.get_chunk(3),'\n')

for i in agg2:
    print(i)
  key1 key2  value1  value2
0  one    a       1       2
1  one    b       3       4
2  one    c       5       6 

  key1 key2  value1  value2
3  one    d       6       8
4  two    a       9      10
5  two    b      11      12
6  two    c      13      14
7  two    d      15      16

1.1.2 写文本的方式

df2 = pd.read_csv('pandas_test.csv')
print(df2)
   1   2   3   4 message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12  python
# 写的方法
df2.to_csv('out_ex1.csv')

1.2 JSON数据

obj = """
{"name":"Wes",
"pet":null,
"places_lived":["United States","Spain","Germany"],
"siblings":[{"age":30,"name":"Scott","pets":["Zeus","Zuko"]},
{"age":38,"name":"Katie","pets":["Sixes","Stache","Cisco"]}]
}
"""
# 导入python的json库
import json
# 将json字符串转换为python类型数据
res = json.loads(obj)
print(res)
{'name': 'Wes', 'pet': None, 'places_lived': ['United States', 'Spain', 'Germany'], 'siblings': [{'age': 30, 'name': 'Scott', 'pets': ['Zeus', 'Zuko']}, {'age': 38, 'name': 'Katie', 'pets': ['Sixes', 'Stache', 'Cisco']}]}
# 将python数据转换为json字符串
obj_1 = json.dumps(res)
print(obj_1)
{"name": "Wes", "pet": null, "places_lived": ["United States", "Spain", "Germany"], "siblings": [{"age": 30, "name": "Scott", "pets": ["Zeus", "Zuko"]}, {"age": 38, "name": "Katie", "pets": ["Sixes", "Stache", "Cisco"]}]}
sib = pd.DataFrame(res['siblings'],columns=['name','age'])
print(sib)
    name  age
0  Scott   30
1  Katie   38

二、数据清洗和准备

import pandas as pd
import numpy as np
data = pd.read_csv(r'guazi.csv')
data
leixingnianfenlichengdidianshoujiayuanjia
0凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.77万34.60万
1奥迪A6L 2014款 TFSI 标准型2014年13.8万公里长沙21.96万44.50万
2本田 思域 2016款 1.8L 自动舒适版2016年4.8万公里长沙8.87万15.20万
3大众 朗逸 2015款 1.6L 自动舒适版2016年10.5万公里长沙7.27万14.90万
4leixingnianfenlichengdidianshoujiayuanjia
.....................
2005大众 途观 2013款 1.8TSI 自动两驱舒适版2014年7.3万公里长沙13.50万25.80万
2006现代ix35 2012款 2.0L 自动两驱精英版GLS2012年7.1万公里长沙8.00万21.30万
2007宝马3系 2014款 320Li 时尚型2015年4.6万公里长沙23.00万38.90万
2008标致308 2014款 乐享版 经典 1.6L 手动优尚型2015年3.0万公里长沙6.20万11.50万
2009大众POLO 2014款 1.6L 自动舒适版2016年2.9万公里长沙7.40万11.30万

2010 rows × 6 columns

2.1 处理缺失数据

方法说明
dropna根据各标签的值中是否存在缺失数据对轴标签进行过滤,可通过阈值调节对缺失值的容忍度
fillna用指定值或插值方法(如ffill或bfill)填充缺失数据
isnull返回之一含有布尔值的对象,这些布尔值表示哪些值是缺失值/NA,该对象的类型与源类型一样
notnullisnull的否定式
data1 = pd.Series(['a','b',np.nan,'d'])
print(data1)
0      a
1      b
2    NaN
3      d
dtype: object
data2 = pd.DataFrame([[1.,6.5,3.],[1.,np.nan,np.nan],[np.nan,np.nan,np.nan],[np.nan,6.7,7.]])
print(data2)
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.7  7.0

2.1.1 判断缺失数据

print(data1.isnull(),'\n')
print(data2.isnull(),'\n')
0    False
1    False
2     True
3    False
dtype: bool 

       0      1      2
0  False  False  False
1  False   True   True
2   True   True   True
3   True  False  False 

print(data1.isnull(),'\n')
print(data2.isnull(),'\n')
0    False
1    False
2     True
3    False
dtype: bool 

       0      1      2
0  False  False  False
1  False   True   True
2   True   True   True
3   True  False  False 

2.1.2 滤除缺失数据

# 方法一:dropna 函数
print(data1.dropna())
0    a
1    b
3    d
dtype: object
# 方法二:使用条件索引
print(data1[data1.notnull()])
0    a
1    b
3    d
dtype: object
# 滤除dataframe数据
print(data2)
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.7  7.0
# 默认 axis=0 滤除包含NaN值的列数据
print(data2.dropna())
     0    1    2
0  1.0  6.5  3.0
# 设置 how 参数为 all,可删除全为 NaN 值的行
print(data2.dropna(how='all'))
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
3  NaN  6.7  7.0
# axis=1,how='all' 删除列中全为NaN值的数据
print(data2.dropna(axis=1,how='all'))
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.7  7.0
df = pd.DataFrame(np.random.randn(7,3))
print(df)
          0         1         2
0  0.915035 -0.558523 -0.197747
1 -0.375031  0.687483 -2.233406
2 -0.713800 -0.495835 -0.739050
3  0.939015 -1.675553  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144
df.iloc[:4,1] = np.nan
df.iloc[:2,2] = np.nan
print(df)
          0         1         2
0  0.915035       NaN       NaN
1 -0.375031       NaN       NaN
2 -0.713800       NaN -0.739050
3  0.939015       NaN  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144
# thresh 参数可以设置删除某行(axis=0)或某列(axis=1)中NaN个数超过thresh的行或列数据
print(df.dropna(thresh=2))
          0         1         2
2 -0.713800       NaN -0.739050
3  0.939015       NaN  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144

2.1.3 填充数据

print(df,'\n')
          0         1         2
0  0.915035       NaN       NaN
1 -0.375031       NaN       NaN
2 -0.713800       NaN -0.739050
3  0.939015       NaN  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144 

# fillna 函数,将所有NaN值填充为0
print(df.fillna(0))
          0         1         2
0  0.915035  0.000000  0.000000
1 -0.375031  0.000000  0.000000
2 -0.713800  0.000000 -0.739050
3  0.939015  0.000000  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144
# 传入字典类型参数可以将key指定的列数据上所有的NaN值替换为value值
# 如果想要本地修改则设置 inplace=True
print(df.fillna({1:0.9,2:0}))
          0         1         2
0  0.915035  0.900000  0.000000
1 -0.375031  0.900000  0.000000
2 -0.713800  0.900000 -0.739050
3  0.939015  0.900000  1.087504
4 -1.645904 -1.092061 -1.585963
5  0.248340 -0.513915  0.377761
6  0.288351 -0.275316 -0.744144
df2 = pd.DataFrame(np.random.randn(6,3))
print(df2)
          0         1         2
0 -0.895130 -0.221522  0.274133
1 -0.704247 -0.532311  0.684838
2 -1.280771 -1.754449  0.215026
3  1.981223 -0.025672 -1.022509
4  0.380020  0.358988 -1.011639
5 -0.873098  1.344166 -0.092629
df2.iloc[2:,1] = np.nan
df2.iloc[4:,2] = np.nan
print(df2)
          0         1         2
0 -0.895130 -0.221522  0.274133
1 -0.704247 -0.532311  0.684838
2 -1.280771       NaN  0.215026
3  1.981223       NaN -1.022509
4  0.380020       NaN       NaN
5 -0.873098       NaN       NaN
# method='ffill' 使用邻近的非NaN填充NaN值
print(df2.fillna(method='ffill'))
          0         1         2
0 -0.895130 -0.221522  0.274133
1 -0.704247 -0.532311  0.684838
2 -1.280771 -0.532311  0.215026
3  1.981223 -0.532311 -1.022509
4  0.380020 -0.532311 -1.022509
5 -0.873098 -0.532311 -1.022509
# limit=2 设置连续的NaN值中填充的个数
print(df2.fillna(method='ffill',limit=2))
          0         1         2
0 -0.895130 -0.221522  0.274133
1 -0.704247 -0.532311  0.684838
2 -1.280771 -0.532311  0.215026
3  1.981223 -0.532311 -1.022509
4  0.380020       NaN -1.022509
5 -0.873098       NaN -1.022509

2.1.4 例子

print(data)
                            leixing  nianfen  licheng  didian  shoujia  \
0           凯迪拉克ATS-L 2016款 28T 时尚型    2016年   2.5万公里      长沙   16.77万   
1              奥迪A6L 2014款 TFSI 标准型    2014年  13.8万公里      长沙   21.96万   
2            本田 思域 2016款 1.8L 自动舒适版    2016年   4.8万公里      长沙    8.87万   
3            大众 朗逸 2015款 1.6L 自动舒适版    2016年  10.5万公里      长沙    7.27万   
4                           leixing  nianfen  licheng  didian  shoujia   
...                             ...      ...      ...     ...      ...   
2005     大众 途观 2013款 1.8TSI 自动两驱舒适版    2014年   7.3万公里      长沙   13.50万   
2006   现代ix35 2012款 2.0L 自动两驱精英版GLS    2012年   7.1万公里      长沙    8.00万   
2007           宝马3系 2014款 320Li 时尚型    2015年   4.6万公里      长沙   23.00万   
2008  标致308 2014款 乐享版 经典 1.6L 手动优尚型    2015年   3.0万公里      长沙    6.20万   
2009        大众POLO 2014款 1.6L 自动舒适版    2016年   2.9万公里      长沙    7.40万   

      yuanjia  
0      34.60万  
1      44.50万  
2      15.20万  
3      14.90万  
4     yuanjia  
...       ...  
2005   25.80万  
2006   21.30万  
2007   38.90万  
2008   11.50万  
2009   11.30万  

[2010 rows x 6 columns]
print(data.fillna(0))
                            leixing  nianfen  licheng  didian  shoujia  \
0           凯迪拉克ATS-L 2016款 28T 时尚型    2016年   2.5万公里      长沙   16.77万   
1              奥迪A6L 2014款 TFSI 标准型    2014年  13.8万公里      长沙   21.96万   
2            本田 思域 2016款 1.8L 自动舒适版    2016年   4.8万公里      长沙    8.87万   
3            大众 朗逸 2015款 1.6L 自动舒适版    2016年  10.5万公里      长沙    7.27万   
4                           leixing  nianfen  licheng  didian  shoujia   
...                             ...      ...      ...     ...      ...   
2005     大众 途观 2013款 1.8TSI 自动两驱舒适版    2014年   7.3万公里      长沙   13.50万   
2006   现代ix35 2012款 2.0L 自动两驱精英版GLS    2012年   7.1万公里      长沙    8.00万   
2007           宝马3系 2014款 320Li 时尚型    2015年   4.6万公里      长沙   23.00万   
2008  标致308 2014款 乐享版 经典 1.6L 手动优尚型    2015年   3.0万公里      长沙    6.20万   
2009        大众POLO 2014款 1.6L 自动舒适版    2016年   2.9万公里      长沙    7.40万   

      yuanjia  
0      34.60万  
1      44.50万  
2      15.20万  
3      14.90万  
4     yuanjia  
...       ...  
2005   25.80万  
2006   21.30万  
2007   38.90万  
2008   11.50万  
2009   11.30万  

[2010 rows x 6 columns]

2.2 数据转换

2.2.1 处理重复数据

data = pd.DataFrame({'k1':['one','two']*3+['two'],
                    'k2':[1,1,2,3,3,4,4]})
print(data)
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
6  two   4
  • duplicated返回布尔型Series表示每行是否为重复行
# 根据前面是否出现过判断重复行
# 默认按照所有列的内容匹配重复
print(data.duplicated())
0    False
1    False
2    False
3    False
4    False
5    False
6     True
dtype: bool
# 传入list参数设置按照哪些列数据匹配重复
print(data.duplicated(['k1']))
0    False
1    False
2     True
3     True
4     True
5     True
6     True
dtype: bool
  • drop_duplicates()过滤重复行
# 默认按照所有列的内容匹配重复
print(data.drop_duplicates())
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
# 传入list参数设置按照哪些列数据匹配重复
print(data.drop_duplicates(['k1']))
    k1  k2
0  one   1
1  two   1
# 设置默认删除前面所有重复的值
print(data,'\n')
print(data.drop_duplicates(keep='last'))
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
6  two   4 

    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
6  two   4

2.2.2 利用函数或映射进行数据转换

data = pd.DataFrame({'food':['Apple','banana','orange','apple','Mango','tomato'],
                    'price':[4,3,3.5,6,12,3]})
print(data)
     food  price
0   Apple    4.0
1  banana    3.0
2  orange    3.5
3   apple    6.0
4   Mango   12.0
5  tomato    3.0
meat = {'apple':'fruit',
       'banana':'fruit',
       'orange':'fruit',
       'mango':'fruit',
       'tomato':'vagetables'}
# 按照某列的数值判断从属类别,并将信息新建到原数据列
data['class'] = data['food'].map(meat)
print(data)
     food  price       class
0   Apple    4.0         NaN
1  banana    3.0       fruit
2  orange    3.5       fruit
3   apple    6.0       fruit
4   Mango   12.0         NaN
5  tomato    3.0  vagetables
# 使用映射函数
print(data,'\n') # 重置了data
data['class'] = data['food'].map(lambda x: meat.get(x.lower()))
print(data)
     food  price
0   Apple    4.0
1  banana    3.0
2  orange    3.5
3   apple    6.0
4   Mango   12.0
5  tomato    3.0 

     food  price       class
0   Apple    4.0       fruit
1  banana    3.0       fruit
2  orange    3.5       fruit
3   apple    6.0       fruit
4   Mango   12.0       fruit
5  tomato    3.0  vagetables

2.2.3 替换值

data = pd.Series([1,-999,2,-1000,3])
print(data)
0       1
1    -999
2       2
3   -1000
4       3
dtype: int64
# replace根据值的内容进行替换
# to_replace设置需要替换的数值列表
# value对应于to_replace的数值位置设置替换值
print(data.replace([-999,-1000],[np.nan,0]))
0    1.0
1    NaN
2    2.0
3    0.0
4    3.0
dtype: float64
# 使用字典参数可等效上述的两个参数
print(data.replace({-999:np.nan,-1000:0}))
0    1.0
1    NaN
2    2.0
3    0.0
4    3.0
dtype: float64

2.2.4 重命名轴索引

data = pd.DataFrame(np.arange(12).reshape((3,4)),
                   index=['Beijing','Tokyo','New York'],
                   columns=['one','two','three','four'])
print(data)
          one  two  three  four
Beijing     0    1      2     3
Tokyo       4    5      6     7
New York    8    9     10    11
# 重新索引(对原索引进行调整)
print(data.reindex(index=['Beijing','New York','Tokyo']),'\n')

# 由于没有与原索引对应,无法实现重命名的任务
print(data.reindex(index=[1,2,3]))
          one  two  three  four
Beijing     0    1      2     3
New York    8    9     10    11
Tokyo       4    5      6     7 

   one  two  three  four
1  NaN  NaN    NaN   NaN
2  NaN  NaN    NaN   NaN
3  NaN  NaN    NaN   NaN
# 方法一:直接替换 index 对象的值
# 大写
tran = lambda x:x[:4].upper()
print(data.index.map(tran),'\n')

# 替换原来的index
data.index = data.index.map(tran)
print(data)
Index(['BEIJ', 'TOKY', 'NEW '], dtype='object') 

      one  two  three  four
BEIJ    0    1      2     3
TOKY    4    5      6     7
NEW     8    9     10    11
# 先重置 data
# 方法二:使用 rename 方法
print(data.rename(index=str.title,columns=str.upper))
          ONE  TWO  THREE  FOUR
Beijing     0    1      2     3
Tokyo       4    5      6     7
New York    8    9     10    11
# 结合字典型对象对标签更新
print(data.rename(index={'Tokyo':'东京'},columns={'three':'第三年'}))
          one  two  第三年  four
Beijing     0    1    2     3
东京          4    5    6     7
New York    8    9   10    11

2.2.5 离散化和面元划分

  • 离散化:将连续的值变成离散值的操作

  • 面元划分:将离散的值划定为指定区间的值(分阶段)

ages = [20,22,25,27,21,23,37,31,61,45,41,32]
# 面元 bin(划定区间)
bins = [18,25,35,60,100]
cuts = pd.cut(ages,bins)
# 将ages中的离散值转换为所属区间值
print(cuts)
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, interval[int64, right]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
# 返回 ages 各元素,所属 bins 区间的下标值
print(cuts.codes)
[0 0 0 1 0 0 2 1 3 2 2 1]
# 返回 ages 各元素,所属 bins 区间
print(cuts.categories)
IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]], dtype='interval[int64, right]')
# 统计区域划分后的各区间的值的个数
print(pd.value_counts(cuts))
(18, 25]     5
(25, 35]     3
(35, 60]     3
(60, 100]    1
dtype: int64
# 设置面元的开闭区间
cuts_1 = pd.cut(ages,bins,right=False)
print(cuts_1)
[[18, 25), [18, 25), [25, 35), [25, 35), [18, 25), ..., [25, 35), [60, 100), [35, 60), [35, 60), [25, 35)]
Length: 12
Categories (4, interval[int64, left]): [[18, 25) < [25, 35) < [35, 60) < [60, 100)]
# 命名区间
names = ['青年','年轻人','中年','老年']
cuts_2 = pd.cut(ages,bins,labels=names)
print(cuts_2)
['青年', '青年', '青年', '年轻人', '青年', ..., '年轻人', '老年', '中年', '中年', '年轻人']
Length: 12
Categories (4, object): ['青年' < '年轻人' < '中年' < '老年']
data = np.random.rand(20)
print(data)
[0.53456858 0.44578249 0.04042052 0.93446914 0.53793848 0.3494597
 0.80669954 0.33582879 0.2548792  0.92986248 0.07492674 0.54910372
 0.63209603 0.8102901  0.22497568 0.04927668 0.9396684  0.83759755
 0.71066308 0.60853243]
# 设置 bins = 4,表示自动根据数值分布将其划分为4个区间
# precision=2 表示设置保留 2 位小数
data_1 = pd.cut(data,4,precision=2)
print(data_1)
[(0.49, 0.71], (0.27, 0.49], (0.04, 0.27], (0.71, 0.94], (0.49, 0.71], ..., (0.04, 0.27], (0.71, 0.94], (0.71, 0.94], (0.49, 0.71], (0.49, 0.71]]
Length: 20
Categories (4, interval[float64, right]): [(0.04, 0.27] < (0.27, 0.49] < (0.49, 0.71] < (0.71, 0.94]]
# qcut 函数
data = np.random.randn(1000)
print(data)
# qcut 自动划分包含等同个数的数的区间
cuts = pd.qcut(data,4)
print(cuts)
[(0.642, 4.048], (-0.726, -0.0328], (0.642, 4.048], (-3.568, -0.726], (0.642, 4.048], ..., (-0.0328, 0.642], (-0.0328, 0.642], (-0.0328, 0.642], (-0.726, -0.0328], (-0.726, -0.0328]]
Length: 1000
Categories (4, interval[float64, right]): [(-3.568, -0.726] < (-0.726, -0.0328] < (-0.0328, 0.642] < (0.642, 4.048]]
pd.value_counts(cuts)
(-3.568, -0.726]     250
(-0.726, -0.0328]    250
(-0.0328, 0.642]     250
(0.642, 4.048]       250
dtype: int64
# 设置自动划分各区间中包含数的个数的比例
cuts = pd.qcut(data,[0,0.1,0.5,0.9,1.])
print(cuts)
[(1.255, 4.048], (-1.336, -0.0328], (1.255, 4.048], (-1.336, -0.0328], (1.255, 4.048], ..., (-0.0328, 1.255], (-0.0328, 1.255], (-0.0328, 1.255], (-1.336, -0.0328], (-1.336, -0.0328]]
Length: 1000
Categories (4, interval[float64, right]): [(-3.568, -1.336] < (-1.336, -0.0328] < (-0.0328, 1.255] < (1.255, 4.048]]
# 按照 (0.1-0):(0.5-0.1):(0.9-0.5):(1.0-0.9) ---> 1:4:4:1 的比例从小到大划分区间
print(cuts.value_counts())
(-3.568, -1.336]     100
(-1.336, -0.0328]    400
(-0.0328, 1.255]     400
(1.255, 4.048]       100
dtype: int64

2.2.6 检测和过滤异常值

data = pd.DataFrame(np.random.randn(1000,4))
print(data)
            0         1         2         3
0    0.058193  0.377252 -0.027805 -0.692871
1   -0.260613  0.703073  0.782897  1.065004
2    0.191974 -1.767126  0.944262  0.578397
3    1.075826 -0.696180  1.029438 -0.704189
4    1.262402  0.781030 -0.736455  0.184382
..        ...       ...       ...       ...
995 -0.218156  1.184946  0.586725  0.718576
996  0.527347 -1.563576 -1.186479 -1.058085
997  1.265693 -0.585655  1.613620 -0.534025
998 -1.508731  0.287481  0.813883 -1.063898
999  0.890795  0.301612  1.200027  0.883201

[1000 rows x 4 columns]
print(data[(np.abs(data)>3).any(axis=1)])
            0         1         2         3
24   3.269307  0.226283  0.620447  1.018873
247  0.263223  3.311795  0.136548 -0.583588
273 -0.078376 -0.159689  0.532239 -3.339462
379 -3.252917 -0.213957 -0.012385 -0.261206
510 -0.605521  1.211071  3.275973  0.522374
719  0.095083  3.432468 -0.490989  1.367091
727 -0.606702 -1.873455 -3.199690  0.290764
data[np.abs(data)>3] = 3
print(data.describe())
                 0            1            2            3
count  1000.000000  1000.000000  1000.000000  1000.000000
mean     -0.030800     0.013330     0.030884     0.020129
std       1.003752     1.006792     0.989630     0.996250
min      -2.936906    -2.931640    -2.786820    -2.997812
25%      -0.747704    -0.634105    -0.618477    -0.651899
50%       0.019667     0.051025     0.034802     0.030156
75%       0.693021     0.660996     0.681150     0.666826
max       3.000000     3.000000     3.000000     3.000000

2.2.7 排列和随机采样

df = pd.DataFrame(np.arange(20).reshape((5,4)))
print(df)
    0   1   2   3
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15
4  16  17  18  19
# 随机生成取自[0,6)不重复且打乱顺序的数组
sam = np.random.permutation(5)
print(sam)
[3 0 2 1 4]
# take 函数,沿着指定轴方向,按照新的index进行排列
print(df.take(sam),'\n')
# 等价于
print(df.reindex(index=sam))
    0   1   2   3
3  12  13  14  15
0   0   1   2   3
2   8   9  10  11
1   4   5   6   7
4  16  17  18  19 

    0   1   2   3
3  12  13  14  15
0   0   1   2   3
2   8   9  10  11
1   4   5   6   7
4  16  17  18  19
# DataFrame 数据的随机采样
print(df.sample(n=3))
    0   1   2   3
0   0   1   2   3
4  16  17  18  19
2   8   9  10  11
# Series 数据的随机采样
ch = pd.Series([5,6,1,6,3])
print(ch)
0    5
1    6
2    1
3    6
4    3
dtype: int64
# 采样个数超出原数据个数,则可使用 replace=True 设置可重复采样
print(ch.sample(n=10,replace=True))
2    1
4    3
1    6
0    5
0    5
1    6
4    3
4    3
3    6
0    5
dtype: int64

2.3 字符串操作

2.3.1 字符串方法

方法说明
count返回子串在字符串中的出现次数(非重叠)
endswith、startwith如果字符串以某个后缀结果(以某个前缀开头),则返回True
join将字符串用作连接其他字符串序列的分隔符
index如果在字符串中找到子串,则返回子串低于个字符所在的位置。如果没有找到,则引发ValueError
find如果在字符串中找到子串,则返回第一个发现的子串的第一个字符所在的位置。如果没有找到,则返回 -1
rfind如果在字符串中找到子串,则返回最后一个发现的子串的第一个字符所在的位置。如果没有找到,则返回 -1
replace用另一个字符串替换指定子串
strip、rstrip、lstrip去除空白符(包括换行符)。相当于对各个元素执行 x.strip()(以及rstrip、lstrip)
split通过指定的分隔符将字符串拆分为一组子串
lower、upper分别将字母字符转换为小写或大写
ljust、rjust用空格(或其他字符)填充字符串的空白侧以返回符合最低宽度的字符串

2.3.2 正则表达式

方法说明
findall、finditer返回字符串中所有的非重叠匹配模式。findall返回的是由所有模式组成的列表,而finditer则通过一个迭代器逐个返回
match从字符串起始位置匹配模式,还可以对模式各部分进行分组。如果匹配到模式,则返回一个匹配项对象,否则返回None
search扫描整个字符串以匹配模式。如果找到则返回一个匹配项对象。跟match不同,其匹配项可以谓语字符串的任意位置,而不仅仅是起始位置
split根据找到的模式将字符串拆分为数段
sub、subn将字符串中的所有的(sub)或前 n 个(subn)模式替换为指定表达式。在替换字符串中可以通过\1、\2等符号表示各分组项
import re
text = 'foo  bar\t bat  \tqq'
print(re.split('\s+',text))
['foo', 'bar', 'bat', 'qq']
res = re.compile('\s+')
print(res.split(text))
['foo', 'bar', 'bat', 'qq']
print(res.findall(text))
['  ', '\t ', '  \t']
print(res.finditer(text))
<callable_iterator object at 0x0000017D0FC71588>

2.3.3 Pandas的矢量化字符串函数

在这里插入图片描述

data = {'a':'dave@qq.com','b':'steve@gmail.com',
       'c':'sam@gmail.com','d':np.nan}
data = pd.Series(data)
print(data)
a        dave@qq.com
b    steve@gmail.com
c      sam@gmail.com
d                NaN
dtype: object
print(data.isnull())
a    False
b    False
c    False
d     True
dtype: bool
# 可使用 Series\DataFrame.str.XXX 对各元素执行相关处理
# 也可使用 Series ---> map  DataFrame ---> applymap 对元素进行映射处理
data.str.contains('@')
a    True
b    True
c    True
d     NaN
dtype: object

2.4 总结

在这里插入图片描述

data = pd.read_csv('guazi.csv')
data
leixingnianfenlichengdidianshoujiayuanjia
0凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.77万34.60万
1奥迪A6L 2014款 TFSI 标准型2014年13.8万公里长沙21.96万44.50万
2本田 思域 2016款 1.8L 自动舒适版2016年4.8万公里长沙8.87万15.20万
3大众 朗逸 2015款 1.6L 自动舒适版2016年10.5万公里长沙7.27万14.90万
4leixingnianfenlichengdidianshoujiayuanjia
.....................
2005大众 途观 2013款 1.8TSI 自动两驱舒适版2014年7.3万公里长沙13.50万25.80万
2006现代ix35 2012款 2.0L 自动两驱精英版GLS2012年7.1万公里长沙8.00万21.30万
2007宝马3系 2014款 320Li 时尚型2015年4.6万公里长沙23.00万38.90万
2008标致308 2014款 乐享版 经典 1.6L 手动优尚型2015年3.0万公里长沙6.20万11.50万
2009大众POLO 2014款 1.6L 自动舒适版2016年2.9万公里长沙7.40万11.30万

2010 rows × 6 columns

# step 1:处理缺失值
(data.isnull()).sum()
leixing     0
nianfen     0
licheng     0
didian      0
shoujia     0
yuanjia    73
dtype: int64
data.dropna(subset=['yuanjia'],inplace=True)
# step 2:删除异常值
data.drop([4,9],inplace=True)
data
leixingnianfenlichengdidianshoujiayuanjia
0凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.77万34.60万
1奥迪A6L 2014款 TFSI 标准型2014年13.8万公里长沙21.96万44.50万
2本田 思域 2016款 1.8L 自动舒适版2016年4.8万公里长沙8.87万15.20万
3大众 朗逸 2015款 1.6L 自动舒适版2016年10.5万公里长沙7.27万14.90万
5凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.77万34.60万
.....................
2005大众 途观 2013款 1.8TSI 自动两驱舒适版2014年7.3万公里长沙13.50万25.80万
2006现代ix35 2012款 2.0L 自动两驱精英版GLS2012年7.1万公里长沙8.00万21.30万
2007宝马3系 2014款 320Li 时尚型2015年4.6万公里长沙23.00万38.90万
2008标致308 2014款 乐享版 经典 1.6L 手动优尚型2015年3.0万公里长沙6.20万11.50万
2009大众POLO 2014款 1.6L 自动舒适版2016年2.9万公里长沙7.40万11.30万

1935 rows × 6 columns

# step 2:处理重复值
(data.duplicated()).sum()
8
data.drop_duplicates(inplace=True)
(data.duplicated()).sum()
0
data
leixingnianfenlichengdidianshoujiayuanjia
0凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.7734.60万
1奥迪A6L 2014款 TFSI 标准型2014年13.8万公里长沙21.9644.50万
2本田 思域 2016款 1.8L 自动舒适版2016年4.8万公里长沙8.8715.20万
3大众 朗逸 2015款 1.6L 自动舒适版2016年10.5万公里长沙7.2714.90万
15Smart smart fortwo 2012款 1.0 MHD 硬顶标准版2014年5.6万公里长沙4.8912.50万
.....................
2005大众 途观 2013款 1.8TSI 自动两驱舒适版2014年7.3万公里长沙13.5025.80万
2006现代ix35 2012款 2.0L 自动两驱精英版GLS2012年7.1万公里长沙8.0021.30万
2007宝马3系 2014款 320Li 时尚型2015年4.6万公里长沙23.0038.90万
2008标致308 2014款 乐享版 经典 1.6L 手动优尚型2015年3.0万公里长沙6.2011.50万
2009大众POLO 2014款 1.6L 自动舒适版2016年2.9万公里长沙7.4011.30万

1927 rows × 6 columns

# step 3 数据类型转换
data['shoujia'] = data['shoujia'].map(lambda x: float(x.replace('万','')))
data
leixingnianfenlichengdidianshoujiayuanjia
0凯迪拉克ATS-L 2016款 28T 时尚型2016年2.5万公里长沙16.7734.60万
1奥迪A6L 2014款 TFSI 标准型2014年13.8万公里长沙21.9644.50万
2本田 思域 2016款 1.8L 自动舒适版2016年4.8万公里长沙8.8715.20万
3大众 朗逸 2015款 1.6L 自动舒适版2016年10.5万公里长沙7.2714.90万
15Smart smart fortwo 2012款 1.0 MHD 硬顶标准版2014年5.6万公里长沙4.8912.50万
.....................
2005大众 途观 2013款 1.8TSI 自动两驱舒适版2014年7.3万公里长沙13.5025.80万
2006现代ix35 2012款 2.0L 自动两驱精英版GLS2012年7.1万公里长沙8.0021.30万
2007宝马3系 2014款 320Li 时尚型2015年4.6万公里长沙23.0038.90万
2008标致308 2014款 乐享版 经典 1.6L 手动优尚型2015年3.0万公里长沙6.2011.50万
2009大众POLO 2014款 1.6L 自动舒适版2016年2.9万公里长沙7.4011.30万

1927 rows × 6 columns

三、数据规整

3.1 层次化索引

import numpy as np
import pandas as pd
data = pd.Series(np.random.randn(9),index=[['a','a','a','b','b','c','c','d','d'],[1,2,3,1,3,1,2,2,3]])
print(data)
a  1    0.959344
   2    2.139239
   3   -1.087872
b  1   -0.622621
   3    0.008807
c  1   -0.610277
   2   -0.671484
d  2    1.298714
   3    1.297636
dtype: float64
# 外层索引获取值
print(data['a'],'\n')
print(data.loc[['b','d']])
1    0.959344
2    2.139239
3   -1.087872
dtype: float64 

b  1   -0.622621
   3    0.008807
d  2    1.298714
   3    1.297636
dtype: float64
# 忽略外层索引的内层索引选取
print(data.loc[:,2])
a    2.139239
c   -0.671484
d    1.298714
dtype: float64
# 设置指定列数据为索引
frame = pd.DataFrame({'a':[0,1,2,3,4,5,6],'b':[7,6,5,4,3,2,1],
                      'c':['one','one','one','two','two','two','two'],
                     'd':[0,1,2,0,1,2,3]})
print(frame)
   a  b    c  d
0  0  7  one  0
1  1  6  one  1
2  2  5  one  2
3  3  4  two  0
4  4  3  two  1
5  5  2  two  2
6  6  1  two  3

3.1.1 set_index设置列数据作为索引

# 设置为外层索引的列数据需要先排序(即将同数值的排到一起)
# drop = False 表示不删除设置为索引值的列
frame2 = frame.set_index(['c','d'])
print(frame2)
       a  b
c   d      
one 0  0  7
    1  1  6
    2  2  5
two 0  3  4
    1  4  3
    2  5  2
    3  6  1

3.1.2 reset_index将索引变为列数据

print(frame2.reset_index())
     c  d  a  b
0  one  0  0  7
1  one  1  1  6
2  one  2  2  5
3  two  0  3  4
4  two  1  4  3
5  two  2  5  2
6  two  3  6  1

3.2 数据连接

3.2.1 pd.merge 函数

  • pd.merge(left,right,how=‘inner’,on=None,left_on=None,right_on=None)

    1. left:合并时左边的DataFrame
    2. right:合并时右边的DataFrame
    3. how:合并的方式,默认 ‘inner’,‘outer’,‘left’,‘right’
    4. on:需要合并的列名,必须两边都有的列名,并以 left 和 right 中的列名的交集作为连接键
    5. left_on:left DataFrame 中用作连接键的列
    6. right_on:right DataFrame 中用作连接键的列
  • 内连接 inner :对两张表都有的键的交集进行联合
    在这里插入图片描述

  • 全连接 outer :对两者表的都有的键的并集进行联合
    在这里插入图片描述

  • 左连接 left:对所有左表的键进行联合
    在这里插入图片描述

  • 右连接 right:对所有右表的键进行联合
    在这里插入图片描述

left = pd.DataFrame({'key':['K0','K1','K2','K3'],
                    'A':['A0','A1','A2','A3'],
                    'B':['B0','B1','B2','B3']})
right = pd.DataFrame({'key':['K0','K0','K2','K3'],
                     'C':['C0','C1','C2','C3'],
                     'D':['D0','D1','D2','D3']})
print(left,'\n')
print(right,'\n')
  key   A   B
0  K0  A0  B0
1  K1  A1  B1
2  K2  A2  B2
3  K3  A3  B3 

  key   C   D
0  K0  C0  D0
1  K0  C1  D1
2  K2  C2  D2
3  K3  C3  D3 

# on='key' 设置在指定列索引上的连接
# how = 'outer' 设置全外连接
print(pd.merge(left,right,on='key',how='outer'))
  key   A   B    C    D
0  K0  A0  B0   C0   D0
1  K0  A0  B0   C1   D1
2  K1  A1  B1  NaN  NaN
3  K2  A2  B2   C2   D2
4  K3  A3  B3   C3   D3
  • pd.merge 处理重复列名
# 处理重复列名
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                        'data' : np.random.randint(0,10,7)})

df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
                        'data' : np.random.randint(0,10,3)})
print(df_obj1,'\n')
print(df_obj2,'\n')
# suffixes 指定重复列索引名在合并后的添加后缀名
print(pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right')))
  key  data
0   b     3
1   b     3
2   a     5
3   c     9
4   a     3
5   a     5
6   b     5 

  key  data
0   a     7
1   b     1
2   d     3 

  key  data_left  data_right
0   b          3           1
1   b          3           1
2   b          5           1
3   a          5           7
4   a          3           7
5   a          5           7
  • pd.merge 函数按索引连接
# 按索引连接
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                        'data1' : np.random.randint(0,10,7)})
df_obj2 = pd.DataFrame({'data2' : np.random.randint(0,10,3)}, index=['a', 'b', 'd'])

print(df_obj1,'\n')
print(df_obj2,'\n')
# right_index = True,设置连接关键字为 key 的情况下,使用 “左列数据,右行索引”的连接方式
print(pd.merge(df_obj1, df_obj2, left_on='key', right_index=True))
  key  data1
0   b      8
1   b      0
2   a      8
3   c      3
4   a      5
5   a      1
6   b      0 

   data2
a      6
b      0
d      3 

  key  data1  data2
0   b      8      0
1   b      0      0
6   b      0      0
2   a      8      6
4   a      5      6
5   a      1      6
left2 = pd.DataFrame(np.arange(1,7).reshape((3,2)),index=list('ace'),columns=['语文','数学'],dtype=np.float64)
right2 = pd.DataFrame(np.arange(7,15).reshape((4,2)),index=list('bcde'),columns=['英语','综合'],dtype=np.float64)
print(left2,'\n')
print(right2,'\n')
    语文   数学
a  1.0  2.0
c  3.0  4.0
e  5.0  6.0 

     英语    综合
b   7.0   8.0
c   9.0  10.0
d  11.0  12.0
e  13.0  14.0 

# 设置两边均为行索引作为连接关键字连接
print(pd.merge(left2,right2,how='outer',left_index=True,right_index=True))
    语文   数学    英语    综合
a  1.0  2.0   NaN   NaN
b  NaN  NaN   7.0   8.0
c  3.0  4.0   9.0  10.0
d  NaN  NaN  11.0  12.0
e  5.0  6.0  13.0  14.0

3.2.2 DataFrame.join 函数

print(left2,'\n')
print(right2,'\n')
    语文   数学
a  1.0  2.0
c  3.0  4.0
e  5.0  6.0 

     英语    综合
b   7.0   8.0
c   9.0  10.0
d  11.0  12.0
e  13.0  14.0 

# join使用两边的行索引作为连接关键字
# 注意:join方法不支持重复列索引名(即:两边存在相同的列索引名的合并)
print(left2.join(right2,how='outer'))
    语文   数学    英语    综合
a  1.0  2.0   NaN   NaN
b  NaN  NaN   7.0   8.0
c  3.0  4.0   9.0  10.0
d  NaN  NaN  11.0  12.0
e  5.0  6.0  13.0  14.0

3.2.3 pd.concat 函数

  • Numpy 中的 concatenate 函数
arr1 = np.random.randint(0, 10, (3, 4))
arr2 = np.random.randint(0, 10, (3, 4))

print(arr1,'\n')
print(arr2,'\n')

print(np.concatenate([arr1, arr2]),'\n')
print(np.concatenate([arr1, arr2], axis=1))
[[0 6 0 0]
 [2 5 7 5]
 [9 9 7 6]] 

[[2 7 4 8]
 [9 2 3 0]
 [0 2 1 3]] 

[[0 6 0 0]
 [2 5 7 5]
 [9 9 7 6]
 [2 7 4 8]
 [9 2 3 0]
 [0 2 1 3]] 

[[0 6 0 0 2 7 4 8]
 [2 5 7 5 9 2 3 0]
 [9 9 7 6 0 2 1 3]]
  • pd.concat
    1. 注意指定轴方向,默认 axis = 0
    2. join 指定合并方式,默认为outer
    3. Series 合并时查看行索引有无重复
df1 = pd.DataFrame(np.arange(6).reshape(3,2),index=list('abc'),columns=['one','two'])

df2 = pd.DataFrame(np.arange(4).reshape(2,2)+5,index=list('ac'),columns=['three','four'])
print(df1,'\n')
print(df2,'\n')


# 默认 axis = 0 是行方向上的数据合并,会自动匹配
# keys 可设置合并后的外层索引值
# 可用于两个DataFrame同列索引对象的数据合并
print(pd.concat([df1,df2],keys=['data1','data2'])) #默认外连接,axis=0
   one  two
a    0    1
b    2    3
c    4    5 

   three  four
a      5     6
c      7     8 

         one  two  three  four
data1 a  0.0  1.0    NaN   NaN
      b  2.0  3.0    NaN   NaN
      c  4.0  5.0    NaN   NaN
data2 a  NaN  NaN    5.0   6.0
      c  NaN  NaN    7.0   8.0
# 使用 行索引 作为连接关键字连接
print(pd.concat([df1,df2],axis=1)) #默认外连接,axis=1
# 等价于 pd.merge(df1,df2,how='outer',left_index=True,right_index=True)
   one  two  three  four
a    0    1    5.0   6.0
b    2    3    NaN   NaN
c    4    5    7.0   8.0

3.3 重塑和轴向旋转

3.3.1 重塑层次化索引

  • stack
    1. 将列索引旋转为行索引,完成层级索引
    2. DataFrame —> Series
data = pd.DataFrame(np.arange(6).reshape((2,3)),
                    index=pd.Index(['老王','小刘'],name='姓名'),
                   columns=pd.Index(['语文','数学','英语'],name='科目'))
print(data)
科目  语文  数学  英语
姓名            
老王   0   1   2
小刘   3   4   5
# 将行索引作为外层索引,列索引作为内层索引
s = data.stack()
print(s,'\n')
print(type(s))
姓名  科目
老王  语文    0
    数学    1
    英语    2
小刘  语文    3
    数学    4
    英语    5
dtype: int32 

<class 'pandas.core.series.Series'>
  • unstack
    1. 将层级索引展开
    2. Series —> DataFrame
    3. 默认操作内层索引,即level=-1
# 将层级索引转换为 DataFrame
print(s.unstack(level=-1),'\n')
# 等价于 print(s.unstack(level='科目'),'\n')

print(s.unstack(level=0),'\n') # 相当于转置
# 等价于 print(s.unstack(level='姓名'),'\n')
科目  语文  数学  英语
姓名            
老王   0   1   2
小刘   3   4   5 

姓名  老王  小刘
科目        
语文   0   3
数学   1   4
英语   2   5 

s1 = pd.Series([0,1,2,3],index=['a','b','c','d'])
s2 = pd.Series([4,5,6],index=['c','d','e'])
print(s1,'\n')
print(s2,'\n')
s = pd.concat([s1,s2],keys=['data1','data2'])
print(s)
a    0
b    1
c    2
d    3
dtype: int64 

c    4
d    5
e    6
dtype: int64 

data1  a    0
       b    1
       c    2
       d    3
data2  c    4
       d    5
       e    6
dtype: int64
# 默认使用内层索引作为DataFrame的列索引,会填充nan值
print(s.unstack())
         a    b    c    d    e
data1  0.0  1.0  2.0  3.0  NaN
data2  NaN  NaN  4.0  5.0  6.0
# stack 方法默认会去除nan值
# 使用 dropna=False 设置不去除 NaN 值
print(s.unstack().stack(),'\n')
print(s.unstack().stack(dropna=False),'\n')
data1  a    0.0
       b    1.0
       c    2.0
       d    3.0
data2  c    4.0
       d    5.0
       e    6.0
dtype: float64 

data1  a    0.0
       b    1.0
       c    2.0
       d    3.0
       e    NaN
data2  a    NaN
       b    NaN
       c    4.0
       d    5.0
       e    6.0
dtype: float64 

3.3.2 轴向旋转

df3 = pd.DataFrame({'date':['2018-11-22','2018-11-22','2018-11-23','2018-11-23','2018-11-24'],
                   'class':['a','b','b','c','c'],
                   'values':[5,3,2,6,1]})
print(df3)
         date class  values
0  2018-11-22     a       5
1  2018-11-22     b       3
2  2018-11-23     b       2
3  2018-11-23     c       6
4  2018-11-24     c       1
df3.pivot('date','class','values')
classabc
date
2018-11-225.03.0NaN
2018-11-23NaN2.06.0
2018-11-24NaNNaN1.0

四、数据分组和聚合

import pandas as pd
import numpy as np
df = pd.read_csv('starbucks_store_worldwide.csv')
df.head()
BrandStore NumberStore NameOwnership TypeStreet AddressCityState/ProvinceCountryPostcodePhone NumberTimezoneLongitudeLatitude
0Starbucks47370-257954Meritxell, 96LicensedAv. Meritxell, 96Andorra la Vella7ADAD500376818720GMT+1:00 Europe/Andorra1.5342.51
1Starbucks22331-212325Ajman Drive ThruLicensed1 Street 69, Al JarfAjmanAJAENaNNaNGMT+04:00 Asia/Dubai55.4725.42
2Starbucks47089-256771Dana MallLicensedSheikh Khalifa Bin Zayed St.AjmanAJAENaNNaNGMT+04:00 Asia/Dubai55.4725.39
3Starbucks22126-218024Twofour 54LicensedAl Salam StreetAbu DhabiAZAENaNNaNGMT+04:00 Asia/Dubai54.3824.48
4Starbucks17127-178586Al Ain TowerLicensedKhaldiya Area, Abu Dhabi IslandAbu DhabiAZAENaNNaNGMT+04:00 Asia/Dubai54.5424.51

4.1 数据分组

  • groupby(by=None,as_index=True)
    1. by:根据什么进行分组,用于确定groupby的分组
    2. as_index:对于聚合输出,返回以组便签为索引的对象,仅对DataFrame
df1 = pd.DataFrame({'fruit':['apple','banana','orange','apple','banana'],
                   'color':['red','yellow','yellow','cyan','cyan'],
                   'price':[8.5,6.8,5.6,7.8,6.4]})
print(df1)
    fruit   color  price
0   apple     red    8.5
1  banana  yellow    6.8
2  orange  yellow    5.6
3   apple    cyan    7.8
4  banana    cyan    6.4
# 返回一个 DataFrameGroupBy 可迭代对象
g = df1.groupby(by='fruit')
print(type(g))
<class 'pandas.core.groupby.generic.DataFrameGroupBy'>
for name,group in g:
    print(name)
    print(group)
    print(type(group))
    print('-'*10)
apple
   fruit color  price
0  apple   red    8.5
3  apple  cyan    7.8
<class 'pandas.core.frame.DataFrame'>
----------
banana
    fruit   color  price
1  banana  yellow    6.8
4  banana    cyan    6.4
<class 'pandas.core.frame.DataFrame'>
----------
orange
    fruit   color  price
2  orange  yellow    5.6
<class 'pandas.core.frame.DataFrame'>
----------
# 选取任意的分组块
print(dict(list(g))['apple'])
   fruit color  price
0  apple   red    8.5
3  apple  cyan    7.8

4.2 聚合方法

函数名描述
count分组中非NA值的数量
sum非NA值的和
mean非NA值的平均值
median非NA值的中位数
std, var标准差和方差
min, max非NA的最小值,最大值
prod非NA值的乘积
first,last非NA值的第一个,最后一个
# 根据水果求价格的平均值
df1.groupby('fruit')['price'].mean()
# 或 df1['price'].groupby(df1['fruit']).mean()
fruit
apple     8.15
banana    6.60
orange    5.60
Name: price, dtype: float64
# as_index 设置返回的聚合数据中,自动新增行索引
df1.groupby('fruit',as_index=False)['price'].mean()
fruitprice
0apple8.15
1banana6.60
2orange5.60
# 使用自定义聚合函数,我们需要将函数传递给agg或aggregate方法,
# 我们使用自定义聚合函数时,会比我们表中的聚合函数慢的多,因为要进行函数调用,数据重新排列
# 自定义聚合方法
def diff(arr):
    return arr.max() - arr.min()
df1.groupby('fruit')['price'].agg(diff)
fruit
apple     0.7
banana    0.4
orange    0.0
Name: price, dtype: float64
# 层级索引下的分组与聚合
df1.groupby(['fruit','color'])['price'].mean()
fruit   color 
apple   cyan      7.8
        red       8.5
banana  cyan      6.4
        yellow    6.8
orange  yellow    5.6
Name: price, dtype: float64
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ModelBulider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值