目录:
- 学习目标
- DataFrame添加列
- 直接赋值添加列数据
- 删除与去重
- 删除
- df.drop删除行数据
- df.drop删除列数据
- 数据去重
- Dataframe去重
- Seriers去重
- 删除
- 修改DataFrame中的数据
- 直接修改数据
- replace函数替换数据
- 按条件使用布尔值修改数据
- 执行自定义函数修改数据
- Series.apply()函数遍历每一个值同时执行自定义函数
- df.apply()函数遍历每一列同时执行自定义函数
- df.apply()函数遍历每一行同时执行自定义函数
- 了解函数向量化
- 总结
1.学习目标
-
知道drop函数删除df的行或列数据
-
知道drop_duplicates函数对df或series进行数据去重
-
知道unique函数对series进行数据去重
-
知道apply函数的使用方法
-
了解numpy.vectorize(func)函数向量化
2.DataFrame添加列
直接赋值添加列数据
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
# 拷贝一份df
df3 = df2.copy()
# 一列数据都是固定值
df3['new col 1'] = 33
# 新增列数据数量必须和行数相等
df3['new col 2'] = [1, 2, 3, 4, 5]
df3['new col 3'] = df3.year * 2
# 分别查看增加数据列之后的df和原df
print(df3)
print(df2)
3.删除与去重
删除
df.drop删除行数据
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
# 拷贝一份df
df3 = df2.copy()
print(df3)
# 默认删除行,按索引值删除,不会在原df上删除,添加参数inplace=True,此时就在原df上进行删除
df4 = df3.drop([0])
print(df4)
# 在原df上进行删除
df3.drop([0], inplace=True)
print(df3)
# 可以删除多行
df5 = df3.drop([2, 4])
print(df5)
# 对series对象按索引值删除
print(df3.GDP)
df6 = df3.GDP.drop([1, 3])
print(df6)
df.drop删除列数据
- df.drop默认删除指定索引值的行
axis=0
或axis='index'
;如果添加参数axis=1
或axis='columns'
,则删除指定列名的列
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
# 拷贝一份df
df3 = df2.copy()
# 一列数据都是固定值
df3['new col 1'] = 33
# 新增列数据数量必须和行数相等
df3['new col 2'] = [1, 2, 3, 4, 5]
df3['new col 3'] = df3.year * 2
print(df3)
df4 = df3.drop(['new col 3'], axis=1)
print(df4)
数据去重
Dataframe去重
- 运行下面的代码获取具有重复数据的df(代码中使用的append函数会在后边《合并与变形》章节中详细介绍)
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
print(df2)
df4 = pd.concat([df2] * 2).reset_index(drop=True)
print(df4)
# 去除重复的数据
# 默认对所有列进行去重,可以通过参数 subset=['列名1','列名2'...] 对指定的列进行去重
df5 = df4.drop_duplicates()
print(df5)
Seriers去重
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df2 = df.head()
print(df2)
df4 = pd.concat([df2] * 2).reset_index(drop=True)
print(df4)
# Seriers对象使用drop_duplicates函数进行去重,返回Series对象
print(df4.country)
df5 = df4.country.drop_duplicates()
print(df5)
# Seriers对象还可以使用unique函数进行去重,返回的ndarray数组
df6 = df4.country.unique()
print(df6)
4.修改DataFrame中的数据
直接修改数据
bash
import pandas as pd
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
# 拷贝一份数据
df5 = df.head().copy()
print(df5)
df5['GDP'] = [5, 4, 3, 2, 1]
print(df5)
replace函数替换数据
bash
import pandas as pd
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df6 = df.head().copy()
print(df6)
# series对象替换数据,返回的还是series对象,不会对原来的df造成修改
df7 = df6.year.replace(1960, 19600)
print(df7)
# 如果加上inplace=True参数,则会修改原始df
df6.country.replace('日本', '扶桑', inplace=True)
print(df6)
# df也可以直接调用replace函数,用法和s.replace用法一致,只是返回的是df对象
df8 = df6.replace(1960, 19600)
print(df8)
按条件使用布尔值修改数据
- 我们可以利用
[s对象的判断表达式]
来选取df中的数据,再进行赋值修改
bash
import pandas as pd
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df7 = df.head().copy()
print(df7)
# 如果country是日本 那就修改GDP为7777
df7['GDP'][df7['country'] == '日本'] = 7777
print(df7)
# 上述步骤解析
# df7['country'] == '日本'
# [df7['country'] == '日本']
# df7['GDP'][df7['country'] == '日本']
执行自定义函数修改数据
- 有时需要我们对df或s对象中的数据做更加精细化的修改动作,并将修改操作封装成为一个自定义的函数;这时我们就可以利用
<s / df>.apply()
来调用我们自定义的函数
Series.apply()函数遍历每一个值同时执行自定义函数
bash
import pandas as pd
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
# Series对象使用apply调用自定义的函数,返回新的Series对象
# 自定义函数必须接收一个参数
def foo(x):
# x此时是s对象中一个数据
# 本自定义函数返回的也是一个数据
if x == '美国':
return '美利坚'
return x
df9 = df8['country'].apply(lambda x: foo(x))
print(df9)
# Series对象使用apply调用自定义的函数,并向自定义函数中传入参数
# 自定义函数必须接收一个参数
def foo(x, arg1):
# x此时是s对象中一个数据
# 本自定义函数返回的也是一个数据
if x == '美国':
return '美利坚'
return arg1
df10 = df8['country'].apply(lambda x: foo(x, arg1='其他国家'))
print(df10)
df.apply()函数遍历每一列同时执行自定义函数
bash
import pandas as pd
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
def foo(s, arg1):
# 此时s参数就是df中的一列数据,s对象
# 函数也必须返回一列数据,s对象
try:
return s + arg1
except:
return s
# 返回df对象
df9 = df8.apply(lambda x: foo(x, arg1=1))
print(df9)
df.apply()函数遍历每一行同时执行自定义函数
- 使用参数
axis=1
,使df.apply()调用的自定义函数按行执行
bash
import pandas as pd
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
def foo(s, arg1):
# 此时s参数就是df中的一行数据,s对象
# 函数也必须返回一行数据,s对象
# print(s)
if s['country'] == arg1:
s.GDP = 6666
return s
return s
# 返回df对象
df9 = df8.apply(lambda x: foo(x, arg1='美国'), axis=1)
print(df9)
小结:
-
s.apply(自定义函数名, arg1=xx, ...)
对s对象中的每一个值,都执行自定义函数,且该自定义函数除了固定接收每一个值作为第一参数以外,还可以接收其他自定义参数 -
df.apply(自定义函数名, arg1=xx, ...)
对df对象中的每一列,都执行自定义函数,且该自定义函数除了固定接收列对象作为第一参数以外,还可以接收其他自定义参数 -
df.apply(自定义函数名, arg1=xx, ..., axis=1)
对df对象中的每一行,都执行自定义函数,且该自定义函数除了固定接收行对象作为第一参数以外,还可以接收其他自定义参数
了解函数向量化
- 运行下面会报错的代码
bash
import pandas as pd
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
# 运行下面会报错的代码
# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)
def bar(s):
# 此时s参数就是df中的一列数据,s对象
# 函数也必须返回一列数据,s对象
if s != 1960:
return s
else:
return s + 1
# 报错
df10 = df9.apply(lambda x: bar(x))
print(df10)
# 运行上述代码会报错
- 上述错误的代码中,
if s != 1960:
报错,s != 1960
返回一组bool值(向量),这个判断表达式没有问题,但和if连在一起使用就会报错----if只能与返回单一bool值(标量)的判断表达式放在一起;此时我们就需要这个if可以和向量放在一起使用,那么这个时候我们就可以使用函数向量化:让整个函数中原来不能和向量进行操作的代码变为可以和向量进行操作【这段话啥意思不理解也没关系,看下边的代码】
bash
import pandas as pd
import numpy as np
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)
def bar(s):
# 此时s参数就是df中的一列数据,s对象
# 函数也必须返回一列数据,s对象
if s != 1960:
return s
else:
return s + 1
# 对原来的bar函数执行np.vectorize(),返回新的函数bar2
bar2 = np.vectorize(lambda x: bar(x))
# 再使用新的bar2函数
df10 = df9.apply(bar2)
print(df10)
- 还可以利用装饰器对函数进行向量化
bash
import pandas as pd
import numpy as np
# 加载数据,构造示例df对象
# 读取数据选取前5行作为一个新的df
df = pd.read_csv('../datas/data_set/1960-2019全球GDP数据.csv', encoding='gbk')
df8 = df.head()
print(df8)
# 构造全是int类型的df
df9 = df8.drop('country', axis=1)
print(df9)
# 使用装饰器
@np.vectorize
def bar(s):
# 此时s参数就是df中的一列数据,s对象
# 函数也必须返回一列数据,s对象
if s != 1960:
return s
else:
return s + 1
# 再使用被向量化装饰器装饰的bar函数
df10 = df9.apply(bar)
print(df10)
5.总结
-
df['列名'] = 标量或向量
修改或添加列 -
<df / s>.drop([索引值1, 索引值2, ...])
根据索引删除行数据 -
df.drop([列名1, 列名2, ...], axis=1)
根据列名删除列数据 -
<df / s>.drop_duplicates()
df或s对象去除重复的行数据 -
s.unique()
s对象去除重复的数据 -
<df / s>.replace('原数据', '新数据', inplace=True)
替换数据-
df或series对象替换数据,返回的还是原来相同类型的对象,不会对原来的df造成修改
-
如果加上inplace=True参数,则会修改原始df
-
-
df['指定列'][df['列名']=='x'] = y
按条件df['列名']=='x'
返回True的对应行的指定列
的值修改为y
-
apply
函数-
s.apply(自定义函数名, arg1=xx, ...)
对s对象中的每一个值,都执行自定义函数,且该自定义函数除了固定接收每一个值作为第一参数以外,还可以接收其他自定义参数 -
df.apply(自定义函数名, arg1=xx, ...)
对df对象中的每一列,都执行自定义函数,且该自定义函数除了固定接收列对象作为第一参数以外,还可以接收其他自定义参数 -
df.apply(自定义函数名, arg1=xx, ..., axis=1)
对df对象中的每一行,都执行自定义函数,且该自定义函数除了固定接收行对象作为第一参数以外,还可以接收其他自定义参数
-
-
new_func = numpy.vectorize(func)
函数向量化,返回一个新的函数