Pandas章节

import numpy as np
import pandas as pd

Series结构

  • series结构,也称Series序列,是pandas常用的数据结构之一,类似于一维数组的结构,由一组数据值(value)和一组标签组成,其中标签与数据值具有对应关系。

  • 标签不是唯一的,但必须是可哈希类型,既支持整数的索引,也支持标签的索引。提供了许多方法涉及索引的操作,nadarry的统计方法已被覆盖,自动排除缺失的数据(表示为NaN)

  • Series可以保存任何数据类型,整数,字符串,浮点数,Python对象等,标签默认为整数,从0开始一次递增

数据结构Series创建

pd.Series(data,index,dtype,name,copy)

  • data:输入的数据,可以是列表,常量,nadarry数组等,如果是字典则保持参数顺序,一组数据(ndarray 类型)。

  • index:数据索引标签,如果不指定,默认从 0 开始。

  • dtype:数据类型,默认会自己判断。

  • name:设置名称。

  • copy:对data进行拷贝数据,默认为 False,仅影响Series和ndarry数组

创建

1)列表/数组作为数据创建Series

# 列表作为数据创建Series
ar_list = [3,10,3,4,5]
print(type(ar_list))

s1 = pd.Series(ar_list)
print(s1)
print(type(s1))
<class 'list'>
0     3
1    10
2     3
3     4
4     5
dtype: int64
<class 'pandas.core.series.Series'>
# 数组作为数据源
np_rand = np.arange(1,6)

s1 = pd.Series(np_rand)
s1
0    1
1    2
2    3
3    4
4    5
dtype: int32
  • 通过index 和 values属性取得对应的标签和值
# 默认为RangeIndex(0,1,2,....,n)
s1.index
RangeIndex(start=0, stop=5, step=1)
# 可以强制转化为列表输出
list(s1.index)
[0, 1, 2, 3, 4]
#返回Series所有值,数据类型为nadarry
print(s1.values,type(s1.values))
[1 2 3 4 5] <class 'numpy.ndarray'>
  • 通过标签取得对应的值,或者修改对应的值
np_rand = np.arange(1,6)
s1 = pd.Series(np_rand)

s1[1] #取得索引为1 的数据
2
s1[2] = 50 #改变索引为2的数据值
s1
0     1
1     2
2    50
3     4
4     5
dtype: int32
s1[-1]  #会报错,去找标签,默认不存在找不动
  • 和列表索引的区别:
    • 默认的索引Rangeindex,不能使用负值,来表示从后往前找元素
    • 获取不存在的索引值对应数据,会报错,但是可以赋值,相当于新增数据
    • 可以新增不同类型索引的数据,
s1[-1] = 20
s1
 0     1
 1     2
 2    50
 3     4
 4     5
-1    20
dtype: int64
#新增不同类型索引的数据
s1['a'] = 40
print(s1.index)
print(s1)
s1[-1]
Index([0, 1, 2, 3, 4, -1, 'a'], dtype='object')
0      1
1      2
2     50
3      4
4      5
-1    20
a     40
dtype: int64





20

2)字典作为数据源创建Series

d = {'a':1,'b':2,'c':3}
ser = pd.Series(data=d)
ser
a    1
b    2
c    3
dtype: int64
  • 通过index 和 values属性取得对应的标签和值
ser.index
Index(['a', 'b', 'c'], dtype='object')
ser.values
array([1, 2, 3], dtype=int64)
  • 通过标签取得对应的值,或者修改对应的值
print(ser)
# ser[10] = 50 
ser['s'] = 50
ser
a    1
b    2
c    3
dtype: int64





a     1
b     2
c     3
s    50
dtype: int64
ser[0] #相当于ser【a】
ser['a']

#如果标签非数值型,既可以用标签获取值,
#如果存在数值型的标签,就不可以用标签的下标获取值
# 也可以用标签的下标获取值
1
  • 使用显示索引的方法定义索引标签
#使用显示索引的方法定义索引标签
data = np.array(['a','b','c','d'])
s = pd.Series(data,index=[100,101,102,103])
s
100    a
101    b
102    c
103    d
dtype: object
  • 从指定索引的字典构造序列
d = {'a':1,'b':2,'c':3}
ser = pd.Series(d,index=['a','b','c'])
ser

a    1
b    2
c    3
dtype: int64
- <b>当传递的索引值未匹配对应的字典键时,使用NaN(非数字)填充。
d = {'a':1,'b':2,'c':3}
ser = pd.Series(d,index=['x','b','z'])
ser
x    NaN
b    2.0
z    NaN
dtype: float64
  • b.name 参数
    可以给一个Series对象命名,也可以给Series数组中的索引列起名,
dict = {
    'beijing':2200,
    'shanghai':2500,
    'shenzhen':1700
}
data1=pd.Series(dict)
data1
beijing     2200
shanghai    2500
shenzhen    1700
dtype: int64
data1.name='City_data'
data1.index.name='city_name'
print(data1)
city_name
beijing     2200
shanghai    2500
shenzhen    1700
Name: City_data, dtype: int64
data1.name
'City_data'
data1
city_name
beijing     2200
shanghai    2500
shenzhen    1700
Name: City_data, dtype: int64
  • 怎么利用给Series的数据和索引起的名字来进行提取
#使用Series创建DataFrame类型
df = pd.DataFrame(data1)
print(df,type(df))
print('='*20)
#输出City_data列的数据和类型
print(df['City_data'],type(df['City_data']))
           City_data
city_name           
beijing         2200
shanghai        2500
shenzhen        1700 <class 'pandas.core.frame.DataFrame'>
====================
city_name
beijing     2200
shanghai    2500
shenzhen    1700
Name: City_data, dtype: int64 <class 'pandas.core.series.Series'>
#使用索引访问单个元素值
s = pd.Series(np.random.rand(5),index=list('abcde'))
print(s['c'])
0.2479647608013883
#使用索引访问多个元素值
s = pd.Series([6,7,8,9,10],index=list('abcde'))
print(s)
#注意需要选择多个标签的值,用[[]]来表示(相当于[]中包含一个列表)
print(s[['a','b','d']])
a     6
b     7
c     8
d     9
e    10
dtype: int64
a    6
b    7
d    9
dtype: int64

3.切片

  • Series使用标签切片末端是包含的,与Python不同
  • Series使用位置切片时,末端是不包含的
s = pd.Series(np.random.rand(10)) 
s
0    0.718067
1    0.385780
2    0.350540
3    0.132534
4    0.329904
5    0.448446
6    0.608292
7    0.189063
8    0.171985
9    0.997119
dtype: float64
#位置索引与标签索引刚好一致,使用切片时,如果是数值会认为
#是Python切片运算 ,不包含末端
s[1:5]
1    0.385780
2    0.350540
3    0.132534
4    0.329904
dtype: float64
s = pd.Series([1,2,3,4,5],index=list('abcde'))
print(s['a':'d'])



# 如果想获得最后三个元素,也可以使用下面的方式
print(s[-3:])
a    1
b    2
c    3
d    4
dtype: int64
c    3
d    4
e    5
dtype: int64

Series数据结构 基本技巧

1.查看前几条和后几条数据

s = pd.Series(np.random.rand(15))

print(s.head()) #默认查看前5条数据
print('-'*10)
print(s.head(1)) #默认查看1条数据
print('-'*10)
print(s.tail())   # 默认查看后5条数据
0    0.264512
1    0.073852
2    0.071084
3    0.480427
4    0.104871
dtype: float64
----------
0    0.264512
dtype: float64
----------
10    0.713403
11    0.785608
12    0.663512
13    0.948365
14    0.163793
dtype: float64

2.重新索引 reindex

  • 使用可选填充逻辑,使Series符合新索引
  • 将NaN 放在一个索引中没有值的位置。除非新索引等于当前索引
s = pd.Series(np.random.rand(5),index=list('abcde'))
print(s)

#新索引在上一个索引中不存在,生成新对象时,对应的值,设置为NaN
s1 = s.reindex(list('cde12'))
print('='*20)
print(s1)
a    0.792699
b    0.690389
c    0.671256
d    0.714217
e    0.117531
dtype: float64
====================
c    0.671256
d    0.714217
e    0.117531
1         NaN
2         NaN
dtype: float64
#设置填充值
s2 = s.reindex(list('cde12'),fill_value=0)
print(s2)
c    0.671256
d    0.714217
e    0.117531
1    0.000000
2    0.000000
dtype: float64

3.对齐运算

  • 是数据清洗的重要过程,可以按索引对齐进行运算,如果没对齐的位置补NaN,最后也可以填充NaN
s1 = pd.Series(np.random.rand(3),index=['kelly','anne','t-c'])

s2 = pd.Series(np.random.rand(3),index=['anne','kelly','lily'])

print(s1)
print('='*10)
print(s2)
print('='*10)
print(s1+s2)

kelly    0.969361
anne     0.138287
t-c      0.252173
dtype: float64
==========
anne     0.728153
kelly    0.591631
lily     0.017278
dtype: float64
==========
anne     0.866441
kelly    1.560993
lily          NaN
t-c           NaN
dtype: float64

4.删除和添加

  • 删除
s = pd.Series(np.random.rand(5),index=list('abcde'))
print(s)

s1 = s.drop('a') # 返回删除后的值,原值不改变,默认inplace=False
print(s1)
print(s)
a    0.573110
b    0.110300
c    0.834439
d    0.608614
e    0.796221
dtype: float64
b    0.110300
c    0.834439
d    0.608614
e    0.796221
dtype: float64
a    0.573110
b    0.110300
c    0.834439
d    0.608614
e    0.796221
dtype: float64
s1 = s.drop('a',inplace=True)
print(s1)
print(s)

#inplace 为True,返回None
None
b    0.110300
c    0.834439
d    0.608614
e    0.796221
dtype: float64
  • 添加
#就是设置一个没有的便签然后赋值
#对应的标签没有就是添加,有就是修改

DataFrame数据类型

dataframe是pandas的重要数据结构之一,是使用pandas进行数据分析过程中最常用的结构之一,可以说掌握了dataframe的用法,就拥有了学习数据分析的基本能力

认识DataFrame结构

  • dataframe 一个表格型的数据结构,既有行标签(index),又有列标签(columns),它也被称为异构数据表,所谓异构指的是表格中每列的数据类型可以不同,可以是字符串,整形或浮点类型等

  • dataframe 的每一列数据都可以看成一个Series结构,只不过,DataFrame为每列数据值增加了一个列标签。其实是从Series的基础上演变而来

  • 同Series一样,DataFrame自带行标签索引,默认为‘隐式索引’即从0开始依次递增,行标签与DataFrame中的数据项一一对应

  • 可以对行和列执行算数运算,结构的行数,列数允许增加删除,每个数据值都可以被修改

创建DataFrame对象

pd.DataFrame(data=None,index=None,columns=None,dtype=None,copy=None)

  • data:一组数据(ndarray、series, map, lists, dict 等类型)。

  • index:索引值,或者可以称为行标签,没有传递index值默认是RangeIndex (0, 1, 2, …, n)。

  • columns:列标签,没有传递columns值默认为 RangeIndex (0, 1, 2, …, n) 。

  • dtype:数据类型。

  • copy:拷贝数据,默认为 False。对于dict数据,为True,重新复制一份,

Pandas DataFrame 是一个二维的数组结构,类似二维数组

1.使用普通的列表创建
data = [1,2,3,4,5]
df = pd.DataFrame(data)
print(df)
   0
0  1
1  2
2  3
3  4
4  5
df = pd.Series(data)
print(df)
0    1
1    2
2    3
3    4
4    5
dtype: int64
#观察可以发现,dataframe多了一个列标签
2.使用嵌套列表创建
#列表中每一个元素代表一行数据
data = [['xiaowang',20],['lily',30],['anne',40]]
#未分配列标签
df = pd.DataFrame(data)

print(df)
#观察可以发现有行标签和列标签
          0   1
0  xiaowang  20
1      lily  30
2      anne  40
#列表中每一个元素代表一行数据
data = [['xiaowang',20],['lily',30],['anne',40]]
#分配列标签
df = pd.DataFrame(data,columns=['name','age'])

print(df)
#观察可以发现有行标签和列标签
       name  age
0  xiaowang   20
1      lily   30
2      anne   40
3.列表嵌套字典创建DataFrame 对象
  • 默认情况下,字典的键被用作列名
data = [{'a':1,'b':2},{'a':5,'b':10,'c':20}]
df = pd.DataFrame(data,index=['first','second'])
print(df)
        a   b     c
first   1   2   NaN
second  5  10  20.0
data = [{'a':1,'b':2},{'a':5,'b':10,'c':20}]
df1 = pd.DataFrame(data,index=['first','second'],columns=['a','b'])

#注意:因为b1 在字典键中不存在,所以对应值为NaN
df2 = pd.DataFrame(data,index=['first','second'],columns=['a','b1'])

print(df1)
print('='*20)
print(df2)
        a   b
first   1   2
second  5  10
====================
        a  b1
first   1 NaN
second  5 NaN
4. 字典嵌套列表创建
data = {'name':['关羽','刘备','张飞','曹操'],'age':[28,34,29,42]}
#通过字典创建DataFrame
df = pd.DataFrame(data)
print(df)
#输入标签
print(df.index)

print(df.columns)

#注意这里使用了默认行标签,也就是RangeIndex
  name  age
0   关羽   28
1   刘备   34
2   张飞   29
3   曹操   42
RangeIndex(start=0, stop=4, step=1)
Index(['name', 'age'], dtype='object')
5.添加自定义的行标签
data = {'name':['关羽','刘备','张飞','曹操'],'age':[28,34,29,42]}
#通过字典创建DataFrame
index = ['r1','r2','r3','r4']
df = pd.DataFrame(data,index=index)

print(df)
   name  age
r1   关羽   28
r2   刘备   34
r3   张飞   29
r4   曹操   42
6. Series创建DataFrame对象
  • 可以传递字典形式的Series,从而创建一个DataFrame对象,其输出结果的行索引是所有index的合集
d = {'one':pd.Series([1,2,3],index=list('abc')),
    'two':pd.Series([1,2,3,4],index=list('abcd'))}
df = pd.DataFrame(d)
print(df)
   one  two
a  1.0    1
b  2.0    2
c  3.0    3
d  NaN    4
7.解决不同列设置自定义数据类型
#创建数据
data = {
    'name':pd.Series(['xiaowang','lily','anne']),
    'age':pd.Series([20,30,40],dtype=float),
    'gender':pd.Series(['男','男','女']),
    'salary':pd.Series([5000,8000,10000],dtype=float)
}

df = pd.DataFrame(data)
print(df)
       name   age gender   salary
0  xiaowang  20.0      男   5000.0
1      lily  30.0      男   8000.0
2      anne  40.0      女  10000.0

列操作DataFrame

  • DataFrame 可以使用列标签来完成数据的选取,添加和删除操作。

1.选取列数据

  • 可以使用索引
data = {'name':['关羽','刘备','张飞','曹操'],'age':[28,34,29,42]}
#通过字典创建DataFrame
index = ['r1','r2','r3','r4']
df = pd.DataFrame(data,index=index)
print(df)
print('name列')
print(df['name'])
print('age列')
print(df['age'])
print('选取多列')
print(df[['name','age']])
# 不能使用切片选取多列

   name  age
r1   关羽   28
r2   刘备   34
r3   张飞   29
r4   曹操   42
name列
r1    关羽
r2    刘备
r3    张飞
r4    曹操
Name: name, dtype: object
age列
r1    28
r2    34
r3    29
r4    42
Name: age, dtype: int64
选取多列
   name  age
r1   关羽   28
r2   刘备   34
r3   张飞   29
r4   曹操   42

2.列添加

  • 使用columns列索引标签可以实现添加新的数据列
d = {'one':pd.Series([1,2,3],index=list('abc')),
    'two':pd.Series([1,2,3,4],index=list('abcd'))}
df = pd.DataFrame(d)

#使用df['列']=值,插入新的数据列
print('====通过Series添加一个新的列======')
df['three']=pd.Series([10,20,30],index=list('abc'))
print(df)

#将已经存在的数据列相加运算,从而创建一个新的列
print('将已经存在的数据列相加运算,从而创建一个新的列')
df['four']=df['one']+df['three']
print(df)
====通过Series添加一个新的列======
   one  two  three
a  1.0    1   10.0
b  2.0    2   20.0
c  3.0    3   30.0
d  NaN    4    NaN
将已经存在的数据列相加运算,从而创建一个新的列
   one  two  three  four
a  1.0    1   10.0  11.0
b  2.0    2   20.0  22.0
c  3.0    3   30.0  33.0
d  NaN    4    NaN   NaN

insert() 方法添加

df.insert(loca,column,value,allow_duplocates)

  • loca 整形,插入索引,必须验证0<=loca<=len(列)
  • column 插入列的标签,类型可以是(字符串/数字/散列对象)
  • value 数值 Series或者数组
  • allow_duplicates 允许重复,可以有相同的列标签数据,默认我False
info = [['王杰',18],['李杰',19],['刘杰',17]]
df = pd.DataFrame(info,columns=['name','age'])
print(df)

#注意是columns参数
#数值1代表插入到columns列表的索引位置
df.insert(2,column='score',value=[91,90,75])
print('=====df.insert插入数据======')
print(df)
  name  age
0   王杰   18
1   李杰   19
2   刘杰   17
=====df.insert插入数据======
  name  age  score
0   王杰   18     91
1   李杰   19     90
2   刘杰   17     75
#可以添加重复列标签数据
df.insert(1,column='score',value=[80,70,90],allow_duplicates=True)
print(df['score'])
   score  score
0     80     91
1     70     90
2     90     75

3.删除数据列

  • 通过del和pop pop有返回值
d = {'one':pd.Series([1,2,3],index=list('abc')),
    'two':pd.Series([1,2,3,4],index=list('abcd')),
    'three':pd.Series([10,20,30],index=list('abc'))}
df = pd.DataFrame(d)
print(df)

#使用del删除
del df['one']
print('====del=====')
print(df)

#使用pop删除
res_pop = df.pop('two')
print('====pop====')
# print(df)
print(res_pop)  #返回值
   one  two  three
a  1.0    1   10.0
b  2.0    2   20.0
c  3.0    3   30.0
d  NaN    4    NaN
====del=====
   two  three
a    1   10.0
b    2   20.0
c    3   30.0
d    4    NaN
====pop====
a    1
b    2
c    3
d    4
Name: two, dtype: int64

行操作 DataFrame

1.loc访问标签选取

  • 行操作需要借助loc属性来完成,按标签或布尔数组访问一组行和列

  • df.loc[行索引名称或条件,列索引名称]

补充 loc使用的是标签索引,iloc使用的是位置索引,列没有位置索引
d = {'one':pd.Series([1,2,3],index=list('abc')),
    'two':pd.Series([1,2,3,4],index=list('abcd'))
   }
df = pd.DataFrame(d)
print('====df原始数据=====')
print(df)
#确定标签为b的数据
print('======标签为b的数据====')
print(df.loc['b'])
====df原始数据=====
   one  two
a  1.0    1
b  2.0    2
c  3.0    3
d  NaN    4
======标签为b的数据====
one    2.0
two    2.0
Name: b, dtype: float64
注意:loc允许接收两个参数分别是行和列

行和列还可以使用切片

#标签为b的行到标签为d的行,对应标签为one的列
df.loc['b':'d']['one']   #使用行标签切片包含结尾值
b    2.0
c    3.0
d    NaN
Name: one, dtype: float64





b    2.0
c    3.0
d    NaN
Name: one, dtype: float64

2. iloc访问数值型索引和切片

  • 使用数据型索引,需要使用iloc属性
  • 直接使用索引,会优先查找的是列标签,如果找不到会报错,列没有位置索引
  • 可以使用iloc :行基于整数位置的按位置选择索引
  • df.iloc[行索引位置,列索引位置]
data = {'name':['关羽','刘备','张飞','曹操'],'age':[28,34,29,42]}
#通过字典创建DataFrame
index = ['r1','r2','r3','r4']
#通过字典创建DataFrame
df = pd.DataFrame(data,index=index)
print(df)

   name  age
r1   关羽   28
r2   刘备   34
r3   张飞   29
r4   曹操   42
对单列多行数据进行查看
df['name'][:3]
r1    关羽
r2    刘备
r3    张飞
Name: name, dtype: object
#取得位置索引为2的数据
df.iloc[2]
name    张飞
age     29
Name: r3, dtype: object
#取得位置索引分别为0和2的数据
print(df.iloc[[0,2]])
#提取多行多列的值
df.iloc[[0,2]][:]
   name  age
r1   关羽   28
r3   张飞   29
nameage
r1关羽28
r3张飞29
#表示行索引为0 ,列索引为1的数据
df.iloc[0,1]
28

3.切片操作多行选取

  • 可以直接使用数值型切片操作行,和使用iloc同样的结果
data = {'name':['关羽','刘备','张飞','曹操'],'age':[28,34,29,42]}
#通过字典创建DataFrame
index = ['r1','r2','r3','r4']
df = pd.DataFrame(data,index=index)
df
nameage
r1关羽28
r2刘备34
r3张飞29
r4曹操42
#取得位置索引1-3行,但是不包含3的数据
print(df.iloc[1:3])  #不包含3
   name  age
r2   刘备   34
r3   张飞   29
#使用切片可以直接提取行,相当于iloc
print(df[1:3])
   name  age
r2   刘备   34
r3   张飞   29

4.添加数据行

  • 使用append(函数) 会在行末追加数据行
df . append(other,ignore_index=False,verify_integrity=False,sort=False)
  • other dataframe 或Series/dict类对象,或这些对象的列表
  • ig_index :默认False,如果为True,将不适用index标签
  • sort 排序
data = {'name':['关羽','刘备','张飞','曹操'],
        'age':[28,34,29,42],
       'salary':[5000,8000,4500,10000]}
df = pd.DataFrame(data)
df
nameagesalary
0关羽285000
1刘备348000
2张飞294500
3曹操4210000
1).追加字典
d2 = {'name':'诸葛亮','age':30}
#追加
df3 = df.append(d2,ignore_index=True)  #如果没有ignore忽略行标签会报错
df3
C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\1221644449.py:3: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df3 = df.append(d2,ignore_index=True)
nameagesalary
0关羽285000.0
1刘备348000.0
2张飞294500.0
3曹操4210000.0
4诸葛亮30NaN
#也可以使用Series
d2 = {'name':'诸葛亮','age':30}
df3 = pd.Series(d2,name='a')
df4 = df.append(df3)
df4
C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\3303151293.py:4: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df4 = df.append(df3)
nameagesalary
0关羽285000.0
1刘备348000.0
2张飞294500.0
3曹操4210000.0
a诸葛亮30NaN
2).追加列表
  • list是一维的,则以列的形式追加

  • list是二维的,则以行的形式追加

  • list是三维的,只添加一个值

  • 使用 append可能会出现相同的index,可以使用ignore_index=True 来避免

data = [
    [1,2,3,4],
    [5,6,7,8]
]
df = pd.DataFrame(data)
print(df)
   0  1  2  3
0  1  2  3  4
1  5  6  7  8
  • list 是二维的
a_1 = [[10,'20',30]]
df4 = df.append(a_1)  #需要添加
print(df4)

print('使用忽略行索引')
df5 = df.append(a_1,ignore_index=True)
print(df5)
    0   1   2    3
0   1   2   3  4.0
1   5   6   7  8.0
0  10  20  30  NaN
使用忽略行索引
    0   1   2    3
0   1   2   3  4.0
1   5   6   7  8.0
2  10  20  30  NaN


C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\4112976180.py:2: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df4 = df.append(a_1)  #需要添加
C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\4112976180.py:6: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df5 = df.append(a_1,ignore_index=True)
  • list是一维的
b = [1,2,3]
df5 = df.append(b,ignore_index=True)
df5
C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\3694321706.py:2: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df5 = df.append(b,ignore_index=True)
0123
012.03.04.0
156.07.08.0
21NaNNaNNaN
32NaNNaNNaN
43NaNNaNNaN

5.删除数据行

  • 可以使用行索引标签,从dataframe中删除某一行数据,如果索引标签存在重复,那么他们将被一起删除
df = pd.DataFrame([[1,2],[3,4]],columns = ['a','b'])

df2 = pd.DataFrame([[5,6],[7,8]],columns = ['a','b'])

df = df.append(df2)
print(df)
df1 = df.drop(0)
print('删除后数据')
print(df1)
   a  b
0  1  2
1  3  4
0  5  6
1  7  8
删除后数据
   a  b
1  3  4
1  7  8


C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\2006458995.py:5: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df = df.append(df2)

行列操作

对单列多行数据进行查看

detail['dishes_name'][:5]
#能看到单列的前5行元素,还有上面的行,列操作中得其他方法

对多列多行数据进行查看

detail = [['order_id','dishes_name']][:5]
#跟上面的iloc方法差不多一样的

常用属性和方法操作汇总 见转载文章和收藏夹

data = {'name':['关羽','刘备','张飞','曹操'],
        'age':[28,34,29,42],
       'salary':[5000,8000,4500,10000]}
df = pd.DataFrame(data)
df
nameagesalary
0关羽285000
1刘备348000
2张飞294500
3曹操4210000

转置

  • 把行和列进行交换
df.T
0123
name关羽刘备张飞曹操
age28342942
salary50008000450010000

axes

  • 返回一个行标签,列标签组成的列表
df.axes
[RangeIndex(start=0, stop=4, step=1),
 Index(['name', 'age', 'salary'], dtype='object')]

dtypes

  • 返回Series,每一列的数据类型
df.dtypes
name      object
age        int64
salary     int64
dtype: object

empty

  • 返回一个布尔值,判断输出的数据对象是否为空,若为True 表示对象为空
df.empty
False
#创建一个空的dataframe
empty_df = pd.DataFrame()
empty_df.empty
True
def my_fun(df):
    if not  df.empty :
        print('提供的数据正常')
    else :
        print('提供的数据为空')
    
my_fun(empty_df)
提供的数据为空

columns

  • 返回dataFrame所有列标签
df.columns
Index(['name', 'age', 'salary'], dtype='object')
#可以通过df.columns的个数获取DataFrame列个数
len(df.columns)
3
df.columns.size
3

shape

  • 返回一个元素,获取行数和列数
df.shape
(4, 3)
row_num,column_num = df.shape
print(row_num,column_num)
4 3

values

  • 以nadarry数组的形式返回其中的数据
df.values
array([['关羽', 28, 5000],
       ['刘备', 34, 8000],
       ['张飞', 29, 4500],
       ['曹操', 42, 10000]], dtype=object)

head() tail() 查看数据

#  获取前几行的数据
print(df.head(1))
#获取后几行的数据
print(df.tail(1))
  name  age  salary
0   关羽   28    5000
  name  age  salary
3   曹操   42   10000

修改列名rename()

DataFrame。rename(index,columns,inplace)
  • index 修改后的行标签
  • columns 修改后的列标签
  • inplace 默认为False,不改变原数据,返回修改后的数据,True修改原数据
可以修改部分行或者列
df
nameagesalary
0关羽285000
1刘备348000
2张飞294500
3曹操4210000
#修改行
df.rename(index={1:'row2',2:'row3'})
nameagesalary
0关羽285000
row2刘备348000
row3张飞294500
3曹操4210000
#修改列
df.rename(columns={'name':'Name','age':'Age'})
NameAgesalary
0关羽285000
1刘备348000
2张飞294500
3曹操4210000
df
nameagesalary
0关羽285000
1刘备348000
2张飞294500
3曹操4210000
#添加inplace,修改原数据
df.rename(index={1:'row2',2:'row3'},columns={'name':'Name','age':'Age'},inplace=True)
df  #可以看到原数据发生了变化
NameAgesalary
0关羽285000
row2刘备348000
row3张飞294500
3曹操4210000

info() 函数

  • 打印df的简要摘要,显示有关df的信息,包括索引的数据类型和列的数据类型非空值的数量和内存使用情况
data = {'name':'诸葛亮','age':30}

df1 = df.append(data,ignore_index=True)
df1
C:\Users\DELL\AppData\Local\Temp\ipykernel_21160\3890177474.py:3: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df1 = df.append(data,ignore_index=True)
NameAgesalaryagename
0关羽28.05000NaNNaN
1刘备34.08000NaNNaN
2张飞29.04500NaNNaN
3曹操42.010000NaNNaN
4NaNNaN[5000, 8000, 4500, 10000][28, 34, 29, 42][关羽, 刘备, 张飞, 曹操]
5NaNNaN[5000, 8000, 4500, 10000][28, 34, 29, 42][关羽, 刘备, 张飞, 曹操]
6NaNNaNNaN30诸葛亮
7NaNNaNNaN30诸葛亮
8NaNNaNNaN30诸葛亮
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8 entries, 0 to 7
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   Name    4 non-null      object 
 1   Age     4 non-null      float64
 2   salary  6 non-null      object 
 3   age     4 non-null      object 
 4   name    4 non-null      object 
dtypes: float64(1), object(4)
memory usage: 448.0+ bytes

df.sort_index()

sort_index(axis=0,ascending=True,inplace=True)
  • 默认根据行标签对所有行排序
  • axis 0 行排序 1列排序
  • ascending True 升序, False 降序
  • inplace 默认False 否则排序后替换原来的数据
df = pd.DataFrame({'b':[1,2,2,3],'a':[4,3,2,1],'c':[1,3,8,2]},index=[2,0,1,3])

df

bac
2141
0233
1228
3312
df.sort_index()
bac
0233
1228
2141
3312
df.sort_index(axis=1)
abc
2411
0323
1228
3132
df.sort_index(axis=1,inplace=True)
df

abc
2411
0323
1228
3132

df.sort_values(by,axis =0,ascendingo=True,inplace=False,kind=‘quicksort’,na_position=‘last’)

  • 既可以根据列数据,也可以根据行数据
  • by 必须制定by参数,即哪几行,哪几列,如果axis=0 by=‘列名’ 反之by=‘行名’
  • axis 0按照列排序,1 按照行排序
  • na_… 默认缺失值排在后面
df = pd.DataFrame({'b':[1,2,2,3],'a':[4,3,2,1],'c':[1,3,8,2]},index=[2,0,1,3])

#b列升序排序
df.sort_values(by='b')
bac
2141
0233
1228
3312
#b列降,a列升
df.sort_values(by=['b','a'],ascending=[False,True])
bac
3312
1228
0233
2141
# 按行
df.sort_values(by=3,axis=1)
acb
2411
0332
1282
3123
#一个行升,一个降
df.sort_values(by=[3,0],axis=1,ascending=[True,False])
acb
2411
0332
1282
3123

1.读写不同数据源的数据

1.读写文本文件

./ 当前路径

…/ 上一级

1.文本文件读取

pd.read_table()
pd.read_csv()
  • filepath 文件路径
  • sep接受String,read_csv 默认为’,’ read_table默认为制表符’[Tab]’
  • header 将某行数据作为列名。
  • names 接受array。表示列名
    • 当names没被赋值时,header会变成0,即选取数据文件的第一行作为列名;
    • 当names被赋值时,那么header会变成None,如果都被赋值,就会实现两个参数的组合功能
  • index_col 表示索引列的位置,本来的索引是RangeIndex,可以将列标签指定为索引
  • dtype 接受dict 写入的数据类型(列名为key,数据格式为values)
  • nrows 表示读取前n行
  • encoding utf-8,gbk。
## 使用read_table读取订单信息表
order = pd.read_table('5/meal_order_info.csv',sep=',',encoding='gbk')
# order
print('使用read_table 读取订单信息表的长度为',len(order))
使用read_table 读取订单信息表的长度为 945
## 使用read_csv 读取订单信息表
order1 = pd.read_csv('5/meal_order_info.csv',sep=',',encoding='gbk')
print(order1,'使用read_csv 读取订单信息表的长度为',len(order1))
     info_id  emp_id  number_consumers  mode  dining_table_id  \
0        417    1442                 4   NaN             1501   
1        301    1095                 3   NaN             1430   
2        413    1147                 6   NaN             1488   
3        415    1166                 4   NaN             1502   
4        392    1094                10   NaN             1499   
..       ...     ...               ...   ...              ...   
940      641    1095                 8   NaN             1492   
941      672    1089                 6   NaN             1489   
942      692    1155                 8   NaN             1492   
943      647    1094                 4   NaN             1485   
944      570    1113                 8   NaN             1517   

     dining_table_name  expenditure  dishes_count  accounts_payable  \
0                 1022          165             5               165   
1                 1031          321             6               321   
2                 1009          854            15               854   
3                 1023          466            10               466   
4                 1020          704            24               704   
..                 ...          ...           ...               ...   
940               1013          679            12               679   
941               1010          800            24               800   
942               1013          735            10               735   
943               1006          262             9               262   
944               1038          589            13               589   

         use_start_time  ...           lock_time cashier_id  pc_id  \
0     2016/8/1 11:05:36  ...   2016/8/1 11:11:46        NaN    NaN   
1     2016/8/1 11:15:57  ...   2016/8/1 11:31:55        NaN    NaN   
2     2016/8/1 12:42:52  ...   2016/8/1 12:54:37        NaN    NaN   
3     2016/8/1 12:51:38  ...   2016/8/1 13:08:20        NaN    NaN   
4     2016/8/1 12:58:44  ...   2016/8/1 13:07:16        NaN    NaN   
..                  ...  ...                 ...        ...    ...   
940  2016/8/31 21:23:48  ...  2016/8/31 21:31:48        NaN    NaN   
941  2016/8/31 21:24:12  ...  2016/8/31 21:56:12        NaN    NaN   
942  2016/8/31 21:25:18  ...  2016/8/31 21:33:34        NaN    NaN   
943  2016/8/31 21:37:39  ...  2016/8/31 21:55:39        NaN    NaN   
944  2016/8/31 21:41:56  ...  2016/8/31 21:32:56        NaN    NaN   

     order_number  org_id  print_doc_bill_num  lock_table_info  order_status  \
0             NaN     330                 NaN              NaN             1   
1             NaN     328                 NaN              NaN             1   
2             NaN     330                 NaN              NaN             1   
3             NaN     330                 NaN              NaN             1   
4             NaN     330                 NaN              NaN             1   
..            ...     ...                 ...              ...           ...   
940           NaN     330                 NaN              NaN             1   
941           NaN     330                 NaN              NaN             1   
942           NaN     330                 NaN              NaN             1   
943           NaN     330                 NaN              NaN             1   
944           NaN     330                 NaN              NaN             1   

           phone  name  
0    18688880641   苗宇怡  
1    18688880174    赵颖  
2    18688880276   徐毅凡  
3    18688880231   张大鹏  
4    18688880173   孙熙凯  
..           ...   ...  
940  18688880307    李靖  
941  18688880305    莫言  
942  18688880327   习一冰  
943  18688880207   章春华  
944  18688880313   唐雅嘉  

[945 rows x 21 columns] 使用read_csv 读取订单信息表的长度为 945
## 使用read_csv 读取订单信息表
order2 = pd.read_csv('5/meal_order_info.csv',sep=',',header=None,encoding='gbk')
print(order2,'使用read_csv 读取订单信息表的长度为',len(order2))


          0       1                 2     3                4   \
0    info_id  emp_id  number_consumers  mode  dining_table_id   
1        417    1442                 4   NaN             1501   
2        301    1095                 3   NaN             1430   
3        413    1147                 6   NaN             1488   
4        415    1166                 4   NaN             1502   
..       ...     ...               ...   ...              ...   
941      641    1095                 8   NaN             1492   
942      672    1089                 6   NaN             1489   
943      692    1155                 8   NaN             1492   
944      647    1094                 4   NaN             1485   
945      570    1113                 8   NaN             1517   

                    5            6             7                 8   \
0    dining_table_name  expenditure  dishes_count  accounts_payable   
1                 1022          165             5               165   
2                 1031          321             6               321   
3                 1009          854            15               854   
4                 1023          466            10               466   
..                 ...          ...           ...               ...   
941               1013          679            12               679   
942               1010          800            24               800   
943               1013          735            10               735   
944               1006          262             9               262   
945               1038          589            13               589   

                     9   ...                  11          12     13  \
0        use_start_time  ...           lock_time  cashier_id  pc_id   
1     2016/8/1 11:05:36  ...   2016/8/1 11:11:46         NaN    NaN   
2     2016/8/1 11:15:57  ...   2016/8/1 11:31:55         NaN    NaN   
3     2016/8/1 12:42:52  ...   2016/8/1 12:54:37         NaN    NaN   
4     2016/8/1 12:51:38  ...   2016/8/1 13:08:20         NaN    NaN   
..                  ...  ...                 ...         ...    ...   
941  2016/8/31 21:23:48  ...  2016/8/31 21:31:48         NaN    NaN   
942  2016/8/31 21:24:12  ...  2016/8/31 21:56:12         NaN    NaN   
943  2016/8/31 21:25:18  ...  2016/8/31 21:33:34         NaN    NaN   
944  2016/8/31 21:37:39  ...  2016/8/31 21:55:39         NaN    NaN   
945  2016/8/31 21:41:56  ...  2016/8/31 21:32:56         NaN    NaN   

               14      15                  16               17            18  \
0    order_number  org_id  print_doc_bill_num  lock_table_info  order_status   
1             NaN     330                 NaN              NaN             1   
2             NaN     328                 NaN              NaN             1   
3             NaN     330                 NaN              NaN             1   
4             NaN     330                 NaN              NaN             1   
..            ...     ...                 ...              ...           ...   
941           NaN     330                 NaN              NaN             1   
942           NaN     330                 NaN              NaN             1   
943           NaN     330                 NaN              NaN             1   
944           NaN     330                 NaN              NaN             1   
945           NaN     330                 NaN              NaN             1   

              19    20  
0          phone  name  
1    18688880641   苗宇怡  
2    18688880174    赵颖  
3    18688880276   徐毅凡  
4    18688880231   张大鹏  
..           ...   ...  
941  18688880307    李靖  
942  18688880305    莫言  
943  18688880327   习一冰  
944  18688880207   章春华  
945  18688880313   唐雅嘉  

[946 rows x 21 columns] 使用read_csv 读取订单信息表的长度为 946
1)names没有被赋值,header也没有被赋值;
  • 这种情况下header为0 ,即选取文件的第一行作为表头
2)names没有被赋值,header被赋值;
  • 不指定names,指定header为1,则选取第二行做表头,第二行下面为数据
order2 = pd.read_excel('5/test.xlsx',header=1)
order2

41714424
030110953
141311476
241511664
pd.read_excel(r'5/test.xlsx',names=['a','b','c'])
abc
041714424
130110953
241311476
341511664
表头信息header=None 会出现列的标签 变为了数值型的索引标签

将文件以csv格式存储 order.to_csv

import os
print('检查文件有没有存储进去',os.listdir('./tmp'))

order.to_csv('tmp/orderInfo.csv',sep=',',index=False)
print('检查文件有没有存储进去',os.listdir('./tmp'))

检查文件有没有存储进去 ['orderInfo.csv']
检查文件有没有存储进去 ['orderInfo.csv']

读取Excel文件 pd.read_excel()

user = pd.read_excel('5/users.xlsx',index_col='age')
print('客户信息',len(user))
user
客户信息 734
USER_IDMYIDACCOUNTNAMEORGANIZE_IDORGANIZE_NAMEDUTY_IDTITLE_IDPASSWORDEMAIL...MODIFYERTELstuNoqqweixinmeal_arithmetic_idarithmetic_namesexpooaddress
age
23.01admin超级管理员admin130根目录NaNNaN202cb962ac59075b964b07152d234b7012@qq.com...1.01.306543e+10ab398125079.0398125079.0NaN22广东广州泰迪科技
NaN981NaN老师teacher328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...1.0NaNNaNNaNNaN87.0基于物品的协同过滤NaNNaNNaN
21.0982NaN叶亦凯sx328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017002NaNNaN86.0关联规则广东广州广州
21.0983NaN邓彬彬lyy328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017003NaNNaN86.0关联规则广东广州广州
22.0984NaN张建涛zad328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017004NaNNaN86.0关联规则广东广州广州
..................................................................
48.01642NaN杜殿雨a771330统计17级NaNNaN202cb962ac59075b964b07152d234b512NaN...NaN1.868888e+102017771NaNNaNNaNNaN江西九江佛山
43.01643NaN杜鹦超a772330统计17级NaNNaN202cb962ac59075b964b07152d234b513NaN...NaN1.868888e+102017772NaNNaNNaNNaN天津广州
23.01644NaN杜小悦a773330统计17级NaNNaN202cb962ac59075b964b07152d234b514NaN...NaN1.868888e+102017773NaNNaNNaNNaN广东广州佛山
37.01645NaN杜雨玲a774330统计17级NaNNaN202cb962ac59075b964b07152d234b515NaN...NaN1.868888e+102017774NaNNaNNaNNaN福建厦门广州
46.01646NaN杜依醇a775330统计17级NaNNaN202cb962ac59075b964b07152d234b516NaN...NaN1.868888e+102017775NaNNaNNaNNaN广西南宁佛山

734 rows × 36 columns

对多行数据进行查看

user.iloc[1:6]
USER_IDMYIDACCOUNTNAMEORGANIZE_IDORGANIZE_NAMEDUTY_IDTITLE_IDPASSWORDEMAIL...MODIFYERTELstuNoqqweixinmeal_arithmetic_idarithmetic_namesexpooaddress
age
NaN981NaN老师teacher328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...1.0NaNNaNNaNNaN87.0基于物品的协同过滤NaNNaNNaN
21.0982NaN叶亦凯sx328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017002NaNNaN86.0关联规则广东广州广州
21.0983NaN邓彬彬lyy328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017003NaNNaN86.0关联规则广东广州广州
22.0984NaN张建涛zad328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017004NaNNaN86.0关联规则广东广州广州
23.0985NaN莫诗怡mf328统计班NaNNaN202cb962ac59075b964b07152d234b70NaN...NaN1.868888e+102017005NaNNaN86.0关联规则广西广州

5 rows × 36 columns

2.DataFrame 的常用属性和方法操作(课本上的)

df.iloc[行索引位置,列索引位置】

detail = pd.read_excel('5/meal_order_detail.xlsx')
print('订单详情表的索引为',detail.index)
print('订单详情表的所有值',detail.values)
print('列名',detail.columns)

订单详情表的索引为 RangeIndex(start=0, stop=2779, step=1)
订单详情表的所有值 [[2956 417 610062 ... nan 'caipu/104001.jpg' 1442]
 [2958 417 609957 ... nan 'caipu/202003.jpg' 1442]
 [2961 417 609950 ... nan 'caipu/303001.jpg' 1442]
 ...
 [6756 774 609949 ... nan 'caipu/404005.jpg' 1138]
 [6763 774 610014 ... nan 'caipu/302003.jpg' 1138]
 [6764 774 610017 ... nan 'caipu/302006.jpg' 1138]]
列名 Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
       'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
       'cost', 'place_order_time', 'discount_amt', 'discount_reason',
       'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
       'emp_id'],
      dtype='object')
detail.head(10)
detail_idorder_iddishes_idlogicprn_nameparent_class_namedishes_nameitemis_addcountsamountscostplace_order_timediscount_amtdiscount_reasonkick_backadd_inpriceadd_infobar_codepicture_fileemp_id
02956417610062NaNNaN蒜蓉生蚝0149NaN2016-08-01 11:05:36NaNNaNNaN0NaNNaNcaipu/104001.jpg1442
12958417609957NaNNaN蒙古烤羊腿0148NaN2016-08-01 11:07:07NaNNaNNaN0NaNNaNcaipu/202003.jpg1442
22961417609950NaNNaN大蒜苋菜0130NaN2016-08-01 11:07:40NaNNaNNaN0NaNNaNcaipu/303001.jpg1442
32966417610038NaNNaN芝麻烤紫菜0125NaN2016-08-01 11:11:11NaNNaNNaN0NaNNaNcaipu/105002.jpg1442
42968417610003NaNNaN蒜香包0113NaN2016-08-01 11:11:30NaNNaNNaN0NaNNaNcaipu/503002.jpg1442
51899301610019NaNNaN白斩鸡0188NaN2016-08-01 11:15:57NaNNaNNaN0NaNNaNcaipu/204002.jpg1095
61902301609991NaNNaN香烤牛排0155NaN2016-08-01 11:19:12NaNNaNNaN0NaNNaNcaipu/201001.jpg1095
71906301609983NaNNaN干锅田鸡0188NaN2016-08-01 11:22:21NaNNaNNaN0NaNNaNcaipu/205003.jpg1095
81907301609981NaNNaN桂圆枸杞鸽子汤0148NaN2016-08-01 11:22:53NaNNaNNaN0NaNNaNcaipu/205001.jpg1095
91908301610030NaNNaN番茄有机花菜0132NaN2016-08-01 11:23:56NaNNaNNaN0NaNNaNcaipu/304004.jpg1095

loc,iloc单列切片查找


detail.loc[:,'dishes_name']  #所有行的这一列
detail.iloc[:,5]             #等价于上面的方法
0         蒜蓉生蚝
1        蒙古烤羊腿
2         大蒜苋菜
3        芝麻烤紫菜
4          蒜香包
         ...  
2774     白饭/大碗
2775       牛尾汤
2776    意文柠檬汁 
2777      金玉良缘
2778      酸辣藕丁
Name: dishes_name, Length: 2779, dtype: object

loc,iloc多列切片

detail.loc[:,['order_id','dishes_name']]  #所有行,这两列

detail.iloc[:,[1,5]]  # 逗号是指这两列,冒号是从1到5
order_iddishes_name
0417蒜蓉生蚝
1417蒙古烤羊腿
2417大蒜苋菜
3417芝麻烤紫菜
4417蒜香包
.........
2774774白饭/大碗
2775774牛尾汤
2776774意文柠檬汁
2777774金玉良缘
2778774酸辣藕丁

2779 rows × 2 columns

loc,iloc花式切片

#列名为...和... 的行名为3的数据为
detail.loc[3,['order_id','dishes_name']]    #是行标签为3的,和列标签为
order_id         417
dishes_name    芝麻烤紫菜
Name: 3, dtype: object
detail.loc[2:6,['order_id','dishes_name']]

#行标签是可以取到6的

#如果用iloc就是按索引来取的,索引的位置就要多取一个
detail.iloc[2:7,[1,5]]
order_iddishes_name
2417大蒜苋菜
3417芝麻烤紫菜
4417蒜香包
5301白斩鸡
6301香烤牛排

loc的行索引位置,可以放条件,而iloc不可以,因为iloc是数值型的索引方式

detail.loc[detail['order_id']==458,['order_id','dishes_name']]
order_iddishes_name
145458蒜香辣花甲
146458剁椒鱼头
147458凉拌蒜蓉西兰花
148458木须豌豆
149458辣炒鱿鱼
150458酸辣藕丁
151458炝炒大白菜
152458香菇鸡肉粥
153458干锅田鸡
154458桂圆枸杞鸽子汤
155458五香酱驴肉\r\n\r\n\r\n
156458路易拉菲红酒干红
157458避风塘炒蟹
158458白饭/大碗

原因在于此处条件返回的为一个布尔值Series。根据Series的构成只要取出该Series的values即可

detail.iloc[(detail['order_id']==458).values,[1,5]]
order_iddishes_name
145458蒜香辣花甲
146458剁椒鱼头
147458凉拌蒜蓉西兰花
148458木须豌豆
149458辣炒鱿鱼
150458酸辣藕丁
151458炝炒大白菜
152458香菇鸡肉粥
153458干锅田鸡
154458桂圆枸杞鸽子汤
155458五香酱驴肉\r\n\r\n\r\n
156458路易拉菲红酒干红
157458避风塘炒蟹
158458白饭/大碗

总结:loc更加灵活多变,代码的可读性更高,iloc的代码简洁,但可读性不高,具体使用哪种方法,根据情况而定,大多数的时候建议使用loc

更新修改df中的数据

#将order_id中的458修改为45800

detail.loc[detail['order_id']==458,'order_id']=45800

#查看
detail.loc[detail['order_id']==45800,'order_id']
145    45800
146    45800
147    45800
148    45800
149    45800
150    45800
151    45800
152    45800
153    45800
154    45800
155    45800
156    45800
157    45800
158    45800
Name: order_id, dtype: int64

为df增添数据

新增1列

#新增
detail['payment'] = detail['counts']*detail['amounts']

#查看
detail['payment'].head(10)
0    49
1    48
2    30
3    25
4    13
5    88
6    55
7    88
8    48
9    32
Name: payment, dtype: int64

删除某列的df数据

drop()函数
  • labels 删除的行或列的标签
  • axis 0和1
  • levels 代表标签所在的级别
  • inplace 默认为False, 代表是否对原数据生效
print(detail.columns) #删除前查看

detail.drop(labels='payment',axis=1)

print(detail.columns)
Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
       'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
       'cost', 'place_order_time', 'discount_amt', 'discount_reason',
       'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
       'emp_id', 'payment'],
      dtype='object')
Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
       'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
       'cost', 'place_order_time', 'discount_amt', 'discount_reason',
       'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
       'emp_id', 'payment'],
      dtype='object')

删除一些行

detail.drop(labels=range(1,11),axis=0,inplace=True)
len(detail)
2769

pandas中的描述性统计函数

  • min最小值
  • max最大值
  • mean均值
  • median
  • ptp极差
  • std() 标准差
  • cov()协方差
  • mode() 众数
  • skew()样本偏度
  • Kurt()样本峰度
  • count()非空值数目
  • quantile() 四分位数
  • mad() 平均绝对离差
  • describe()描述统计
print(detail[['counts','amounts']].describe())
            counts      amounts
count  2769.000000  2769.000000
mean      1.111593    45.343084
std       0.626521    36.841316
min       1.000000     1.000000
25%       1.000000    25.000000
50%       1.000000    35.000000
75%       1.000000    56.000000
max      10.000000   178.000000
print('订单信息表dishes_name的描述统计结果为\n',detail['dishes_name'].describe())
订单信息表dishes_name的描述统计结果为
 count      2769
unique      157
top       白饭/大碗
freq         91
Name: dishes_name, dtype: object

自定义函数(当自带的函数满足不了自己的需求可以自己定义一个函数)

剔除表中全为空值或所有元素取值相同的列

## 定义一个函数去除全为空值的列和标准差为0的列
##非空个数为0和方差为0
def dropNullStd(data):
    beforelen = data.shape[1] ##操作前数据记录
    colisNull = data.describe().loc['count'] == 0 #空值的列
    for i in range(len(colisNull)):
        if colisNull[i]:   #等于0
            data.drop(colisNull.index[i],axis=1,inplace=True)
    
    stdisZero = data.describe().loc['std'] == 0  ## 标准差为0
    for i in range(len(stdisZero)):
        if stdisZero[i]:
            data.drop(stdisZero.index[i],axis=1,inplace=True)
    afterlen = data.shape[1]
    
    print('去除的列的数目为',beforelen-afterlen)
    print('去除后数据的形状为',data.shape)
    
dropNullStd(detail)
去除的列的数目为 0
去除后数据的形状为 (2769, 10)

3.转化与处理时间序列数据(参考转载文章)

转换字符串为标准时间(to_datetime函数)

order = pd.read_table('5/meal_order_info.csv',sep=',',encoding='gbk')
print('进行转换前订单信息表lock_time类型',order['lock_time'].dtypes)
order['lock_time'] = pd.to_datetime(order['lock_time'])
print('转换后类型为',order['lock_time'].dtype)
进行转换前订单信息表lock_time类型 object
转换后类型为 datetime64[ns]
order.axes
[RangeIndex(start=0, stop=945, step=1),
 Index(['info_id', 'emp_id', 'number_consumers', 'mode', 'dining_table_id',
        'dining_table_name', 'expenditure', 'dishes_count', 'accounts_payable',
        'use_start_time', 'check_closed', 'lock_time', 'cashier_id', 'pc_id',
        'order_number', 'org_id', 'print_doc_bill_num', 'lock_table_info',
        'order_status', 'phone', 'name'],
       dtype='object')]

Timestamp类型时间是有限制的

pd.Timestamp.min
pd.Timestamp.max
Timestamp('2262-04-11 23:47:16.854775807')
  • 还可以将数据单独提取出来准换为DatetimeIndex或者PeriodIndex (很少用)
  • 转换为Period的时候需要注意,需要通过制定参数freq参数制定时间间隔,常用的时间间隔有
    • Y 年
    • M 月
    • D 日
    • H 时
    • T 分钟
    • S 秒
  • 两个数据可以用来创建时间序列数据
dateIndex = pd.DatetimeIndex(order['lock_time'])
print('转换为DatetimeIndex后数据的类型\n',type(dateIndex))

periodIndex = pd.PeriodIndex(order['lock_time'],freq='S')
print('转换为PeriodIndex后数据的类型为\n',type(periodIndex))
转换为DatetimeIndex后数据的类型
 <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
转换为PeriodIndex后数据的类型为
 <class 'pandas.core.indexes.period.PeriodIndex'>

提取时间序列信息

year1 = [i.year for i in order['lock_time']]
print('lock_time中的年份的数据前5个信息',year1[:5])
month1 = [i.month for i in order['lock_time']]
print('lock_time中的月份的数据前5个信息',month1[:5])
day1 = [i.day for i in order['lock_time']]
print('lock_time中的日期的数据前5个信息',day1[:5])
weekday1 = [i.weekday() for i in order['lock_time']]
print('lock_time中的星期的数据前5个信息',weekday1[:5])

lock_time中的年份的数据前5个信息 [2016, 2016, 2016, 2016, 2016]
lock_time中的月份的数据前5个信息 [8, 8, 8, 8, 8]
lock_time中的日期的数据前5个信息 [1, 1, 1, 1, 1]
lock_time中的星期的数据前5个信息 [0, 0, 0, 0, 0]
print('DatetimeIndex的星期标号数据前5个为',dateIndex.weekday[:5])

print('periodIndex的星期标号数据前5个为',periodIndex.weekday[:5])

DatetimeIndex的星期标号数据前5个为 Float64Index([0.0, 0.0, 0.0, 0.0, 0.0], dtype='float64', name='lock_time')
periodIndex的星期标号数据前5个为 Int64Index([0, 0, 0, 0, 0], dtype='int64', name='lock_time')

加减时间数据(Timedelta)

## 将lock_time数据向后平移一天

time1 = order['lock_time']+pd.Timedelta(days=1)
print(order['lock_time'][:5])
print(time1)
0   2016-08-01 11:11:46
1   2016-08-01 11:31:55
2   2016-08-01 12:54:37
3   2016-08-01 13:08:20
4   2016-08-01 13:07:16
Name: lock_time, dtype: datetime64[ns]
0     2016-08-02 11:11:46
1     2016-08-02 11:31:55
2     2016-08-02 12:54:37
3     2016-08-02 13:08:20
4     2016-08-02 13:07:16
              ...        
940   2016-09-01 21:31:48
941   2016-09-01 21:56:12
942   2016-09-01 21:33:34
943   2016-09-01 21:55:39
944   2016-09-01 21:32:56
Name: lock_time, Length: 945, dtype: datetime64[ns]
## 减除了可以减days=几天
## 还可以减一个具体的日期
timeDelta = order['lock_time']-pd.to_datetime('2017-1-1')
timeDelta

0     -153 days +11:11:46
1     -153 days +11:31:55
2     -153 days +12:54:37
3     -153 days +13:08:20
4     -153 days +13:07:16
              ...        
940   -123 days +21:31:48
941   -123 days +21:56:12
942   -123 days +21:33:34
943   -123 days +21:55:39
944   -123 days +21:32:56
Name: lock_time, Length: 945, dtype: timedelta64[ns]

任务实现

order = pd.read_table('5/meal_order_info.csv',sep=',',encoding='gbk')

#时间字符串转化为标注时间格式
order['use_start_time'] = pd.to_datetime(order['use_start_time'])
order['lock_time'] = pd.to_datetime(order['lock_time'])

print('查看转换后的数据类型',order[['use_start_time','lock_time']].dtypes)


#提取菜品数据里面的年月日和星期信息

year = [i.year for i in order['lock_time']]
month = [i.month for i in order['lock_time']]
day = [i.day for i in order['lock_time']]
week = [i.week for i in order['lock_time']]   #提取周信息
weekday = [i.weekday() for i in order['lock_time']]  #提取星期信息


#查询订单信息表的时间统计信息
timemin = order['lock_time'].min()
timemax = order['lock_time'].max()
timem


查看转换后的数据类型 use_start_time    datetime64[ns]
lock_time         datetime64[ns]
dtype: object





Timestamp('2016-08-31 21:56:12')

4.分组聚合进行组内计算

对菜品信息详情根据订单编号分组

detail = pd.read_excel('5/meal_order_detail.xlsx')
detailGroup = detail[['order_id','counts','amounts']].groupby(by='order_id')
detailGroup

<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000021D65FE6AC0>

GroupBy对象常用的描述性统计方法

  • count() 计算分组的数目
  • head() max() mean median
  • size std min() sum
  • cumcount 对每个分组中的组员进行标记,0 - n-1
detailGroup.mean().head(10)
detailGroup.size()
order_id
137      6
165     18
166      5
171      7
177      4
        ..
1309    13
1314    12
1317    18
1319     9
1323    15
Length: 278, dtype: int64

使用agg方法聚合数据

使用agg 求当前数据的统计量

#订单详情表的菜品销量与售价的和与均值
detail[['counts','amounts']].agg([np.sum,np.mean])
countsamounts
sum3088.000000125992.000000
mean1.11119145.337172
# 使用agg分别求字段的不同统计量
print('分别求的是销量的和   售价的均值')
detail.agg({'counts':np.sum,'amounts':np.mean})
分别求的是销量的和   售价的均值





counts     3088.000000
amounts      45.337172
dtype: float64
#使用agg求不同字段的不同数目的统计量
detail.agg({'counts':np.sum,'amounts':[np.mean,np.sum]})
countsamounts
sum3088.0125992.000000
meanNaN45.337172

在agg 中使用自定义的函数

#自定义函数求和的两倍
def DoubleSum(data):
    s = data.sum()*2
    return s
d1 = detail.agg({'counts':DoubleSum},axis=0).head()
d2 = detail[['counts']].agg(DoubleSum)
print(d2)
# detail['counts'][:].sum()
counts    6176
dtype: int64
使用agg方法能够实现对每一个字段每一组使用相同的函数,如果需要对不同的字段应用不同的函数,则可以和DataFrame中的agg方法相同
# 用agg 方法做简单聚合
detailGroup.agg(np.mean).head(10)
detailGroup.agg(np.std).head(3)
countsamounts
order_id
1371.22474535.200379
1650.38348252.193613
1660.54772341.829415

使用apply方法聚合数据

  • 只能够作用于整个DataFrame或Series上
  • 与agg的不同在于,不能对不同字段应用不同函数
detailGroup[['counts','amounts']].apply(np.mean)
F:\Anaconda\lib\site-packages\numpy\core\fromnumeric.py:3438: FutureWarning: In a future version, DataFrame.mean(axis=None) will return a scalar mean over the entire DataFrame. To retain the old behavior, use 'frame.mean(axis=0)' or just 'frame.mean()'
  return mean(axis=axis, dtype=dtype, out=out, **kwargs)
countsamounts
order_id
1371.50000032.333333
1651.16666752.944444
1661.40000048.200000
1711.42857136.285714
1771.00000034.250000
.........
13091.15384634.076923
13141.00000042.333333
13171.00000067.222222
13191.00000067.777778
13231.00000050.933333

278 rows × 2 columns

使用transform方法聚合数据

detailGroup[['counts','amounts']].transform(lambda x : x*2).head(4)
countsamounts
0298
1296
2260
3250
实现组内离差标准化
  • (均值-最小值)/(最大值-最小值)
detailGroup.apply(lambda x :( x.mean()-x.min())/(x.max()-x.min())).head()
order_idcountsamounts
order_id
137NaN0.1666670.319728
165NaN0.1666670.260026
166NaN0.4000000.409709
171NaN0.1428570.477922
177NaNNaN0.570312

任务实现

  • 按时间对菜品订单信息进行拆分
  • 使用agg 方法计算单日菜品销售的平均单价和售价中位数
  • 使用apply方法统计单日菜品销售数目
detail = pd.read_excel('5/meal_order_detail.xlsx')

# 将时间转换为时间格式
detail['date'] = [i.date() for i in detail['place_order_time']]

#按时间对菜品订单进行拆分
detailGroup = detail[['date','counts','amounts']].groupby(by='date')
# for i ,j in detailGroup:
#     display(i,j)

#求平均单价和售价中位数
detailGroup['amounts'].agg([np.mean,np.median]).head()


#求菜品销售数目
detailGroup['counts'].apply(np.sum)
meanmedian
date
2016-08-0143.16129033.0
2016-08-0244.38405835.0
2016-08-0343.88535038.0
2016-08-0452.42361139.0
2016-08-0544.92746137.0

5.创建透视表与交叉表

透视表:根据一个或多个键值对数据进行聚合,根据行或列的分组键将数据划分到各个区域的过程

pd.pivot_table(data,value=None,index=None,columns=None,aggfunc=np.mean,margins=True,dropna=False)

  • data 接收df,表示创建表的数据
  • values 接收字符串。用于指定想要聚合的数据字段名,默认使用全部数据
  • index 接收string或list 表示行分组键
  • columns 表示列分组键
  • aggfunc 接收函数,表示聚合函数,默认为mean
  • margins 表示汇总(total)的开关,设为True后,结果集中会出现‘ALL’的行和列,默认为True
  • dropna 表示是否删掉全为NaN的列,默认为False
以order_id 作为分组键创建的订单透视表
detail = pd.read_excel('5/meal_order_detail.xlsx')
detailPivot = pd.pivot_table(detail[['order_id','counts','amounts']],index='order_id')
detailPivot.head()
amountscounts
order_id
13732.3333331.500000
16552.9444441.166667
16648.2000001.400000
17136.2857141.428571
17734.2500001.000000
#指定聚合函数
detailPivot1 = pd.pivot_table(detail[['order_id','counts','amounts']],index='order_id',aggfunc=np.sum)
detailPivot1.head()

amountscounts
order_id
1371949
16595321
1662417
17125410
1771374
detailPivot2 = pd.pivot_table(detail[['order_id','dishes_name','counts','amounts']],index=['order_id','dishes_name'],aggfunc=np.sum)

detailPivot2.head(10)


amountscounts
order_iddishes_name
137农夫山泉NFC果汁100%橙汁61
凉拌菠菜271
番茄炖牛腩\r\n351
白饭/小碗14
西瓜胡萝卜沙拉261
麻辣小龙虾991
16538度剑南春801
一品香酥藕101
凉拌萝卜丝201
啤酒鸭481
#通过设置columns参数可以指定列分组

detailPivot3 = pd.pivot_table(detail[['order_id','dishes_name','counts','amounts']],
                              index='order_id',
                              columns='dishes_name',
                              aggfunc=np.sum)
detailPivot3.head()

#将透视表存储
detailPivot3.to_excel(r'5/detailPivot3.xlsx')

detailPivot3.iloc[:5,:5]
amounts
dishes_name42度海之蓝北冰洋汽水38度剑南春50度古井贡酒52度泸州老窖
order_id
137NaNNaNNaNNaNNaN
165NaNNaN80.0NaNNaN
166NaNNaNNaNNaNNaN
171NaNNaNNaNNaNNaN
177NaNNaNNaNNaNNaN

当全部数据列数很多时,若只想要显示某列,可以通过指定values参数来实现

detailPivot4 = pd.pivot_table(detail[['order_id','dishes_name','counts','amounts']],
                              index='order_id',
                              values='counts',
                             aggfunc=np.sum)

detailPivot4.head()
counts
order_id
1379
16521
1667
17110
1774

当某些数据不存在时,会自动填充NaN,指定fill_value

detailPivot5 = pd.pivot_table(detail[['order_id','dishes_name','counts','amounts']],
                              index='order_id',
                              columns='dishes_name',
                              aggfunc=np.sum,fill_value=0)
detailPivot5.head()
amounts...counts
dishes_name42度海之蓝北冰洋汽水38度剑南春50度古井贡酒52度泸州老窖53度茅台一品香酥藕三丝鳝鱼三色凉拌手撕兔不加一滴油的酸奶蛋糕...香辣腐乳炒虾香酥两吃大虾鱼香肉丝拌面鲜美鳝鱼鸡蛋、肉末肠粉麻辣小龙虾黄尾袋鼠西拉子红葡萄酒黄油曲奇饼干黄花菜炒木耳黑米恋上葡萄
order_id
1370000000000...0000010000
165008000010000...0000000010
1660000000000...0000000000
1710000000000...0000000000
1770000000000...0000000000

5 rows × 318 columns

更改margins参数,查看汇总数据

detailPivot6 = pd.pivot_table(detail[['order_id','dishes_name','counts','amounts']],
                              index='order_id',
                              columns='dishes_name',
                              aggfunc=np.sum,
                             fill_value=0,
                             margins=True)
detailPivot6.iloc[-5:,-6:]
counts
dishes_name麻辣小龙虾黄尾袋鼠西拉子红葡萄酒黄油曲奇饼干黄花菜炒木耳黑米恋上葡萄All
order_id
13140000012
13170000018
1319100009
13230000015
All6616515183088

使用crosstab函数创建交叉表,主要用于计算分组频率。

  • 交叉表时透视表的一种,其参数保持一致,不同之处在于crosstab中的index,columns,values填入的都是对应的从Dataframe中取出的一列。

  • index 行索引键

  • columns 列索引键

  • values 聚合数据

  • rownames 行分组键名

  • colnames 列分组键名

detailCross = pd.crosstab(    index=detail['order_id'],
                              columns=detail['dishes_name'],
                              values=detail['counts'],
                              aggfunc=np.sum)
detailCross.iloc[:5,:5]
dishes_name42度海之蓝北冰洋汽水38度剑南春50度古井贡酒52度泸州老窖
order_id
137NaNNaNNaNNaNNaN
165NaNNaN1.0NaNNaN
166NaNNaNNaNNaNNaN
171NaNNaNNaNNaNNaN
177NaNNaNNaNNaNNaN
任务实现
  • 创建订单详情表单日菜品成交总额与总数透视表
  • 创建订单详情表单日单个菜品成交总额交叉表
detail = pd.read_excel('5/meal_order_detail.xlsx')

detail['place_order_time'] = pd.to_datetime(detail['place_order_time'])
detail['date'] = [i.date() for i in detail['place_order_time']]

#透视表
PivotDetail = pd.pivot_table(detail[['date','dishes_name','counts','amounts']],
                            index = 'date',
                            aggfunc = np.sum,
                            margins = True)

# 交叉表
CrossDetail = pd.crosstab(index=detail['date'],
                         columns=detail['dishes_name'],
                         values=detail['amounts'],
                         aggfunc=np.sum,margins=True)
display(PivotDetail.iloc[-5:])
display(CrossDetail.iloc[-5:,-5:])
amountscounts
date
2016-08-0731306761
2016-08-086532171
2016-08-097155167
2016-08-1010231227
All1259923088
dishes_name黄尾袋鼠西拉子红葡萄酒黄油曲奇饼干黄花菜炒木耳黑米恋上葡萄All
date
2016-08-07230.032.0105.099.031306
2016-08-0846.0NaNNaN33.06532
2016-08-09138.0NaN35.099.07155
2016-08-1046.0NaN70.033.010231
All736.080.0525.0561.0125992
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值