Python数据操作(2)

数据操作

将数据挑选出来之后,我们通常要根据需求对数据进行进一步的操作,比如数值替换、排序、计数等等

数值操作主要有:数值替换、数值排序、数值删除、插入新的行或列、apply和applymap函数。

数值替换

一对一的替换

1
2
3
df = pd.read_excel(r'数值操作.xlsx')

df.replace('张天峰', '张三丰') # 返回一个新的DataFrame。是一个“凡是...则...”修改

一对多的替换

1
df.replace([2698, 1390, 1029], 999) # 将表格中包含列表中的数值全部替换成999,返回新的DataFrame, 是一个“凡是...则...”修改

多对多替换

1
df.replace({2698 : 999, 1029 : 1000}) # 将表格中的所有2698替换成999,将所有的1029替换成1000,返回新的DataFrame, 是一个“凡是...则...”修改。实际上是一个多点替换,只能实现点对点替换

条件替换

在后面“apply和applymap的用法”中有讲解

数值排序

根据某一列数据进行排序

1
df.sort_values(by = '消费金额', ascending = False)

根据多列数据进行排序

1
df.srot_values(by = ['消费金额', '年龄'], ascending = [False, True]) # ascending有优先级,如果第一优先级重了则考虑第二优先级,以此类推

数值删除

删除NaN值

1
df.dropna() # 只能删除数据类型为np.nan的值

按列删除

1
2
3
4
df.drop(['消费金额', '购买日期'], axis = 1) # drop()默认删行。按列删除的话需要传入列名,之后再指定axis参数(1为列,0为行), 非原地修改,需要指定inplace = True

# 或者使用
df.drop(columns = ['消费金额', '购买日期']) # 由于指定了columns参数,所以不需要指定axis参数

根据列的位置索引进行删除

1
2
df.drop(df.columns[[4, 5]], axis = 1) # 没使用columns参数,所以还是要带上axis=1
df.drop(df.columns[[1: 5]], axis = 1) # 也可以使用切片语法,适合于删除连续的列

删除行

1
2
3
df.drop([0, 1, 3]) # 这种方式必须传行的标签值,只有当行标签为默认的数字时,才能传数字

df.drop(df.index[1:4]) # 通过index来删行

插入新的数据

插入操作两个关键要素:

  1. 在哪里插入?
  2. 要插入什么?

pandas无单独的行插入操作,所以在插入行的时候需要将DataFrame拆分再合并,插入新行在DataFrame的拆分中会有体现。

插入列

1
df.insert(2'新列', [i for i in range(10)]) # 在第三列处插入新的列。第一个参数是列的索引,第二个参数是新列的列名,第三个参数是新列里面的值,该方法会原地生效

insert方法比较适合于在指定位置插入新列

在DataFrame最后插入新列

1
df['另外的新列'] = [random.random() for _ in range(10)] # 注意for _ in range(10)中_的使用

apply()和applymap()函数的使用

apply()方法

apply()方法作用于列

替换

1
2
3
df['消费金额'].apply(lambda x : str(x) + '元') # 为消费金额所有元素后面加上单位

df['带单位的消费金额'] = df['消费金额'].apply(lambda x : str(x) + '元') # 生成新列

applymap()方法

applymap()方法作用于DataFrame中的每个元素,所以一定注意数据类型

1
df.applymap(lambda x : str(x) + 'OK') # 整个DataFrame中所有元素字符串‘OK’

针对行来进行数据处理

1
2
3
df.iloc[2].apply(lambda x: str(x) + 'good') # 针对某一行,后面所有元素加上good

df.iloc[5 : 9].applymap(lambda x : str(x) + 'good') # 由于iloc返回的还是DataFrame,所以还是使用applymap()

apply()方法只能用于一行/一列数据(Series),applymap()方法适用于DataFrame

条件修改

1
df['消费金额'].apply(lambda x : 499 if x <= 500 else 999 if x >= 1000 else x) # 使用lambda表达式来确定x。注意多分支时lambda表达式的写法

注:

lambda语句中单个语句的写法:语句 if 判断条件 else 语句

lambda表达式中多个if的语法:语句 if 判断条件 else 语句 if 判断条件 else 语句

数据运算

常见的运算方法有:算术运算、比较运算、汇总运算等

算术运算

1
2
3
df = pd.read_excel(r'数据运算.xlsx')

df['两年之和'] = df['Sale2015'] + df['Sale2016'] # 加减乘除都可以

比较运算

1
df[df['Sale2020'] < 3600]

汇总运算

求和

1
df['Sale2015'].sum()

求值的个数

1
df['Sale2015'].count()

求平均值

1
df['Sale2015'].mean()

最大值

1
df['Sale2015'].max()

最小值

1
df['Sale2015'].min()

中位数

1
df['Sale2015'].median()

众数

1
df['Sale2015'].mode()

方差

1
df['Sale2015'].var()

标准差

1
df['Sale2015'].std()

分位数

1
df['Sale2015'].quantile(q = 0.25) # 1/4分位数

时间序列操作

时间序列是一种经常遇到的数据集合。python中获取当前的时间及年月日

1
2
3
4
5
6
7
8
9
from datetime import datetime

datetime.now() # 当前的日期时间
datetime.now().year() # 当前的年,依此类推,月:month();日:day();等等

datetime.now().weekday() # 判断今天是星期几,返回值+1
datetime.now().isocalendar() # 获取当前时间是一年中的第几周以及当前是星期几,返回值是[年,周,星期几]

datetime.now().strftime('%F' '%D') # 指定时间的显示格式,%F格式是2020-07-08,%D格式是07/08/2020

pandas提供的日期时间的常见操作

1
2
3
4
5
df = pd.read_excel(r'时间序列.xlsx', index_col[3]) # 如果里面的时间不能被pandas识别,则需要给定parse_dates参数.此处第三列是pandas可识别的datetime,所以可以直接把它作为索引

df['2019'] # 返回2019年内的所有数据
df['2019-08'] # 返回2019年8月的所有数据
df['2019-08-01' : '2019-08-20'] # 返回2019-08-01到2019-08-20时间段内的所有数据

注:这种方法使用的前提必须将时间设置为索引

时间索引变成普通索引

1
df.reset_index() # 去掉了日期列的索引属性。该方法非原地生效,需要指定inplace = True

时间类型做比较运算

1
2
3
df[df['购买日期'] > '2019-08-10'] # 可以直接使用字符串

df[df['购买日期'] > datetime(2019,9,10)] # 使用datetime构造也可以

计算时间偏移

1
2
3
4
from datetime import timedata

date = datetime(2020, 3, 20, 19, 50) # 构造一个时间
date + timedata(days = 1) # 增加天数,时分秒月日以此类推

利用pandas自带的库来进行时间偏移运算

1
2
3
4
5
from pandas.tseries.offsets import Day, Hour, Minute

date + Day(1) # 加一天
date + Hour(1) # 加一小时
date + Minute(10) # 加10分钟,加满不会进位到小时

DataFrame的拼接操作

1
2
3
4
df1 = pd.read_excel(r'数据拼接.xlsx', sheet_name = 'data1')
df1 = pd.read_excel(r'数据拼接.xlsx', sheet_name = 'data2') # 读入一个文件的两个sheet

pd.concat([df1, df2], ignore_index = True) # 默认是行方向的拼接, 后面的参数忽略掉以前的index,重新编号

注:如果拼接的两个元素的列个数不同,则少的那一列会用NaN填充

列方向拼接

1
pd.concat([df1, df2], axis = 1) # 没有的值置为NaN

如何插入一行新的数据

1
2
3
4
5
6
7
8
9
10
11
df_first = df[0 : 5]
df_second = df[5:]

df_new = pd.DataFrame({'订单编号': 'A076',
'客户姓名' : '老八',
'唯一识别码' : 888,
'购买日期' : '2019-08-18',
'年龄' : 30,
'消费金额' : 8888}, index=[1])

pd.concat([df_first, df_new, df_second], ignore_index = True) # 先拆分再拼接

数据分组

按照单列进行统计

1
2
3
4
5
df = pd.read_excel(r'数据分组.xlsx')

df.groupby('学生ID') # 按照“学生ID”来分组
df.groupby('学生ID').count() # 来统计每个组的个数
df.groupby('学生ID').sum() # sum操作只针对于数值类型的列,类型不符合的话不参与计算

按照多列进行统计

1
2
df.groupby(['学生ID', '科目']).count() # 按照学生ID和科目一起统计。先按照学生进行分组,再按照每个学生的科目进行分组
df.groupby(['学生ID', '科目'])['授课老师'].count() # 可以只取出感兴趣的列

aggregate()方法的使用

它可以同时在指定的统计列上做不同的统计计算

1
2
3
df.groupby('所在年级')['成绩'].aggregate(['count', 'sum']) # 对所选列同时做两种不同的操作

df.groupby('所在年级').aggregate({'科目' : 'count', '成绩' : 'mean'}) # 不同的列做不同的计算