Python基础
数字处理函数
Python提供了用于数字处理的内置函数和内置模块(math),使用内置模块,需要先导入 import math。
内置函数 | math模块 | ||
---|---|---|---|
abs(-5) | 返回绝对值 | math.ceil(2.3) | 返回不小于x 的最小整数 |
divmod(9,4) | 返回商和余数 | math.floor(2.3) | 返回不大于x 的最大整数 |
eval('a*a+1') | 返回字符串中的表达式结果 | math.fabs(-5) | 返回x 的绝对值 |
max(1,2,3,4) | 返回最大值 | math.factorial(5) | 返回非负数x 的阶乘 |
min(1,2,3,4) | 返回最小值 | math.fmod(9,4) | 返回x 除于y 的余数 |
pow(2,3) | 返回2的3次方,等价于2**3 | math.fsum([0.1,0.1,0.1,0.1]) | 求和,比sum 更精确 |
round(1,56) | 四舍五入,只有一个参数是返回整数 | math.gcd(12,8) | 返回x 和y 的最大公约数 |
round(1.567,2) | 四舍五入,保留2为小数 | math.trunc(15.67) | 返回x 的整数部分 |
sum({1,2,3,4}) | 求和 | math.pi | 返回π值,3.141592653589793 |
字符串的切片
字符串的切片也称分片,它利用索引范围从字符串中获得连续的多个字符(即子字符串)。字符串切片的基本格式:x[ start : end : step]
,返回字符串x
中从偏移量start
开始、到偏移量end
之前的子字符串,切片默认情况下是返回字符串中的多个连续字符,可以通过step
步长参数来跳过中间的字符。start
、end
和step
参数均可省略,start
默认为0
,end
默认为字符串长度,step
默认为1
。
x = 'abcdef'
print(x[1:4]) # 返回偏移量为1到3的字符 bcd
print(x[1:]) # 返回偏移量为1到末尾的字符 bcdef
print(x[:4]) # 返回从字符串开头到偏移量为3的字符 abcd
print(x[:-1]) # 除最后一个字符,其他字符全部返回 abcde
print(x[:]) # 返回全部字符 abcdef
x = '0123456789'
print(x[1:7:2]) # 返回偏移量为1、3、5的字符 135
print(x[::2]) # 返回偏移量为偶数的全部字符 02468
print(x[7:1:-2]) # 返回偏移量为7、5、3的字符 753
print(x[::-1]) # 将字符串反序返回 9876543210
字符串是有序的字符集合,可用
for
循环迭代处理字符串,for item in 'abcdefghijk': print(item,end='\t')
字符串处理函数
字符串是 str
类型的对象,Python
提供了一系列方法用于字符串的处理。常用的字符串处理方法如下:
方法名 | 描述 |
---|---|
len(str) | 返回 str 的长度,即包含的字符个数 |
str(info) | 将非字符串数据转换为字符串 |
capitalize(str) | 将字符串第一个字母大写,其余字母小写,返回新的字符串 |
count(sub[, start[, end]]) | 返回字符串sub 在当前字符串的[start, end] 范围内出现的次数,省略范围时会查找整个字符串 |
startswith(prefix[, start[, end]]) | 判断当前字符串的[start, end] 范围内的子字符串是否以sub 字符串开始 |
endswith(suffix,[, start[, end]]) | 判断当前字符串的[start, end] 范围内的子字符串是否以sub 字符串结尾 |
find(sub[, start[, end]]) | 在当前字符串的[start, end] 范围内查找子字符串sub ,返回sub 第一次出现的位置,没有找到时返回-1 |
format(args) | 字符串格式化,将字符串中用{} 定义的替换域依次用参数args 中的数据替换,print('My name is {0},age is {1}'.format('Tome', 23)) |
ljust/rjust(width[, fillchar]) | 当字符串长度小于width 时,在字符串末尾填充fillchar ,使其长度等于width 。默认填充字符为空格 |
lower()/upper() | 将字符串中的字母全部转换成小写/大写 |
replace(old, new[, count]) | 将当前字符串包含的old 字符串替换为new 字符串,省略count 时会替换全部old 字符串。指定count 时,最多替换count 次 |
split([sep],[maxsplit]) | 将字符串按照sep 指定的分隔字符串分解,返回包含分解结构的列表。省略sep 时,以空格作为分隔符 |
'sep'.join(iterable) | 按照sep 指定的分割符连接序列对象(iterable ),返回拼接后的字符串 |
日期和时间数据类型
Python标准库中包含用于日期、时间、日历数据的数据类型,主要用到datetime
、time
和calendar
模块。
函数 | 说明 |
---|---|
datetime.datetime.now() | 获取当前系统时间 |
datetime.date(year,month,day) | 日期(年、月、日) |
datetime.time(hour, minute, second, microsecond, tzinfo) | 时间(时、分、秒、毫秒) |
datetime.datetime(year, month, day,hour, minute, second, microsecond, tzinfo) | 日期和时间 |
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) | 两个datetime的差(日、秒、毫秒),也可以做日期加减运算 |
datetime.tzinfo() | 用于存储时区信息的基本类型 |
datetime.datetime.strptime(datetime_str, formatter) | 把字符串日期转为日期对象 |
datetime_obj.strftime(formattter) | 把日期对象转为指定格式的字符串 |
import datetime
datetime.datetime.now() # 获取当前系统时间
date = datetime.date(2019,11,12) # 封装指定日期
print(date.year,date.month,date.day) # 获取年月日
date = datetime.time(23,12,12,100) # 封装指定时间
print(date.hour,date.minute,date.second,date.microsecond) # 获取时分秒
datetime.datetime.now()+datetime.timedelta(-10) # 日期加减操作
# 日期相差结果,注意需要保证类型一致
delta = datetime.datetime.now() - datetime.datetime(2019,11,12,23,12,12) # datetime.timedelta(days=1479, seconds=37384, microseconds=61401)
delta.seconds # 获取相差的秒数
datetime.datetime.strptime('2019-11-12','%Y-%m-%d') # 日期字符串转为日期对象
datetime.datetime.now().strftime('%Y年%m月%d日') # 日期对象转为指定格式的字符串
列表
列表是Python中最具灵活性的有序集合对象类型。和字符串不同的是,列表具有可变长度、异构以及任意嵌套列表的特点。列表是可变对象,支持在原处修改。
列表常量用方括号表示,例如,[1,2,'abc']
,也可以使用list()
函数来创建。
列表基本操作包括:创建列表、求长度、合并、重复、迭代、关系判断、索引和分片等。
函数名称 | 说明 |
---|---|
append(item) | 在列表末尾添加一个数据 |
del | 删除列表中指定数据或分片 |
count(item) | 返回item在列表中出现的次数 |
clear() | 删除列表中的全部数据 |
insert(index,item) | 在指定位置插入数据 |
index(item) | 返回列表中第一个值为item的元素的索引 |
remove(item) | 用于删除列表中的指定值,如果有重复值,则删除第1个 |
reverse() | 将列表中数据的位置反转 |
pop([index]) | 用于删除指定位置的对象,省略位置时删除列表的最后一个对象,同时返回被删除的对象 |
sort([key=func, reverse=True/False]) | 将列表排序,若列表对象全部是数字,则将数字从小到大排序。若列表对象全部是字符串,则按字典顺序排序。它还支持自定义排序,可用key参数指定一个函数,sort 方法将列表元素作为参数调用该函数,用函数返回值代替列表元素完成排序。 |
# 创建列表
print([1, 2, 3, 4, ('a', 'b'), [12, 34]]) # [1, 2, 3, 4, ('a', 'b'), [12, 34]]
print(list('abcd')) # ['a', 'b', 'c', 'd']
print(list(range(-2, 3))) # [-2, -1, 0, 1, 2]
# 求长度
print(len([1, 2, 3, 4, ('a', 'b'), [5, 6]])) # 6
# 合并
print([1, 2] + ['abc', 20])
# 重复
print([1, 2] * 5)
# 关系判断
print(2 in [1, 2, 3])
# 分片
list1 = list(range(10))
print(list1[:5]) # [0, 1, 2, 3, 4]
print(list1[3:10:2]) # [3, 5, 7, 9]
print(list1[10:3:-2]) # [9, 7, 5]
list1 = [1, 2]
del list1[0] # 删除第1个元素
list1.clear() # 清空列表
# 排序
price_list = [{'price': 76}, {'price': 99}, {'price': 84}]
price_list.sort(key=lambda item: item.get('price'))
print(price_list) # [{'price': 76}, {'price': 84}, {'price': 99}]
列表推导式
列表推导式提供了从序列创建列表的简单途径。通常应用程序将一些操作应用于某个推导序列的每个元素,用其获得的结果作为生成新列表的元素,或者根据确定的判定条件创建子序列。
语法格式为:[ <expr1> for k in L if <expr2> ]
元组
元组是一种固定长度、不可变的Python对象序列。元组和字符串一样,不可改变,即不能给元组的一个独立的元素赋值。元组和列表看起来不同的一点是:元组用的是圆括号()
,而列表用的是方括号[]
。
与字符串一样,元组之间可以使用 + 号和 * 号进行运算。
# 创建元组
print((2,)) # 包含一个对象的元组,不能缺少逗号 (2,)
print(tuple('abcde')) # 参数为可迭代对象 ('a', 'b', 'c', 'd', 'e')
print(tuple(item * 2 for item in range(5))) # 使用解析结构创建元组 (0, 2, 4, 6, 8)
# 求长度
print(len((1, 2, 3, 4, 5))) # 5
# 合并
t1 = (1, 2) + ('ab', 'cd') + (2.45,) # (1, 2, 'ab', 'cd', 2.45)
print(t1)
# 重复
print((1, 2) * 3) # (1, 2, 1, 2, 1, 2)
# 关系判断
print(2 in t1) # True
# 索引和分片
t2 = tuple(range(10)) # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
print(t2[1]) # 1
print(t2[-1]) # 9
print(t2[2:5]) # (2, 3, 4)
# #元组的拆分
a,b,c = (1, 5, 7)
print(a, b, c)
字典
字典,也称映射,是一个由键/值对组成的非排序可变集合体。键值对在字典中以下面的方式标记: dict = {key1 : value1, key2 : value2 }
键/值对用冒号分割,而各个元素之间用逗号分割,所有元素都包括在花括号中。值得注意的是,字典中的键必须是唯一的,只能使用不可变的对象来作为字典的键,字典中的键/值对是没有顺序的。
函数名称 | 说明 |
---|---|
clear() | 删除全部字典对象 |
copy() | 复制字典对象 |
get(key[,default]) | 返回键 key 映射的值。如果键key 不存在,返回空值,可用default 参数指定键不存在时的返回值。 |
pop(key[,default]) | 从字典中删除键值对,并返回被删除的映射值。若键不存在,则返回default 。若键不存在且未指定default 参数时,删除键会出错。 |
popitem() | 从字典中删除键值对,同时返回被删除的键值对元组。空字典调用该方法会产生KeyError 错误。 |
setdefault(key[,default]) | 用于返回映射值或者为字典添加键值对。指定的键key 在字典中存在时,返回其映射值。若指定的键key 不存在,则将键值对key:default 添加到字典中。省略default 时,添加的映射值默认为None 。 |
update(other) | update() 方法用于为字典添加键值对。参数other 可以时另一个字典或用赋值格式表示的元组。若字典已存在同名的键,则该键的映射值被覆盖。 |
items() | 返回键值对 视图,视图对象支持迭代操作,不支持索引。当字典对象发生改变时,字典视图可实时反映字典的改变。 |
keys() | 返回字典中所有键的视图 |
values() | 返回字典中全部值的视图 |
x = dict(name='Tom', age=25)
y = x
# 复制字典对象
yc = x.copy()
print(y is x, yc is x) # 判断是否引用相同对象 True False
# 获取指定key映射的值
print(x.get('name')) # 返回映射值 Tom
print(x.get('addr')) # 不存在的键返回空值 None
print(x.get('addr', 'xxx')) # 不存在的键返回指定值 xxx
# 获取或添加
print(x.setdefault('name')) # 返回指定键的映射值 Tom
print(x.setdefault('sex')) # 键不存在,为字典添加“键:值”对,映射值默认为None None
print(x.setdefault('addr', 'CQ')) # 添加“键:值”对 CQ
print(x) # {'name': 'Tom', 'age': 25, 'sex': None, 'addr': 'CQ'}
# 添加或修改
x.update({'age': 30, 'sex': '女'}) # 添加“键:值”对,并覆盖同名键的映射值
print(x) # {'name': 'Tom', 'age': 30, 'sex': '女', 'addr': 'CQ'}
x.update(name='Mike') # 修改映射值
x.update(code=110, tel='123456') # 添加“键:值”对
print(x) # {'name': 'Mike', 'age': 30, 'sex': '女', 'addr': 'CQ', 'code': 110, 'tel': '123456'}
# 删除指定key的键值对象
print(x.pop('name')) # 删除键并返回映射值 Mike
print(x.pop('id', 'xxx')) # 删除不存在的键,返回default参数值 xxx
# print(x.pop('other')) # 删除不存在的键,未指定default参数,出错 KeyError: 'other'
# 删除字典元素,并以元组的形式返回删除的元素,如果字典为空,则报错 KeyError: 'popitem(): dictionary is empty'
print(x.popitem()) # ('tel', '123456')
# 返回 键值对 视图
entity = x.items() # dict_items([('age', 30), ('sex', '女'), ('addr', 'CQ'), ('code', 110)])
print(list(entity)) # [('age', 30), ('sex', '女'), ('addr', 'CQ'), ('code', 110)]
# 返回 键 视图,值 视图
keys = x.keys() # dict_keys(['age', 'sex', 'addr', 'code'])
vals = x.values() # dict_values([30, '女', 'CQ', 110])
集合
集合是一个由唯一元素组成的非排序集合体。也就是说,集合中的元素没有特定顺序,集合中没有重复项。可以使用大括号{ }
或者set()
函数创建集合,但是,创建一个空集合必须用 set()
,因为{ }
是用来创建一个空字典。
集合对象元素的值不支持修改,但是可以复制
集合、为集合添加
或删除
元素。
函数名称 | 说明 |
---|---|
copy() | .复制集合对象 |
remove(item)/discard(item) | 删除指定元素,删除不存在时会报错/删除不存在时不会报错 |
add(item) | 添加一个元素 |
pop() | 随机删除一个元素,并返回该元素 |
update({item1,item2,...}) | 添加多个元素 |
clear() | 删除集合中的全部元素 |
x = {1, 2}
print(x.copy()) # 复制集合对象
x.add('abc') # 为集合添加一个元素
x.update({10, 20}) # 为集合添加多个元素
x.remove(10) # 从集合中删除指定元素,删除不存在元素时会报错
x.discard(15) # 移除元素
print(x.pop()) # 从集合中随机删除一个元素,并返回该元素 1
x.clear() # 删除集合中的全部元素 set()
集合元素是不可改变的,因此不能将可变对象放入集合中;集合、列表和字典对象均不能加入集合;元组可以作为一个元素加入集合。
Series
Series是一个类似一维数组的对象,它能够保存任何类型的数据,主要由一组数据和与之相关的索引两部分构成。
Pandas的Series类对象的创建语法:pandas.Series(data=None, index=None, dtype=None, copy=False)
- data:表示传入的数据。
- index:表示索引,唯一且与数据长度相等,默认会自动创建一个从0~N的整数索引。
- dtype:数据的类型。
- copy:是否复制数据,默认是False。
s1 = pd.Series([1,2,3,4,5],index=['a','b',1,8,9],name="nums")
s1.index # Index(['a', 'b', 1, 8, 9], dtype='object')
s1.values # array([1, 2, 3, 4, 5], dtype=int64)
type(s1.values) # numpy.ndarray
s1 + 10
s1.sum()
s1[8] # 通过索引取值
s1[s1>3] # 通过条件取值
Series常用方法
Series.unique()
:去除重复元素Series.nunique()
:统计去重后的元素个数Series.isnull()
:检测那些元素为空,为空则返回TrueSeries.notnull()
:检测那些元素为非空,不为空的返回Ture
DataFrame
DataFrame是一个类似于二维数组或表格的对象,它每列的数据可以是不同的数据类型。与Serise的结构相似,DataFrame的结构也是由索引和数据组成的,不同的是,DataFrame的索引不仅有行索引,还有列索引,数据可以有多列。
Pandas的DataFrame类对象的创建语法:pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
- index:行标签。若不设置该参数,则默认会自动创建一个从0~N的整数索引。
- columns:列标签。若不设置,同样会自动创建一个从0~N的整数索引。
DataFrame常用属性和方法
df.head()
默认获取前5行df.head(n)
获取前n行df.tail()
默认获取后5行df.tail(n)
获取后n行df.sample(n)
随机抽取n行显示df.sample(frac=0.6)
随机抽取60%的行df.info()
获取对象中元素的完整信息,包括行/列标签、数据类型、是否有空值、占用的内存大小等df.index
获取所有行标签df.columns
获取所有列标签df.values
获取所有元素的值df.T
对象中元素的行/列数据转换
DataFrame数据的查询
在数据分析中,选取需要的数据进行分析处理是最基本的操作,在Pandas中通过索引完成数据的选取,除了使用之前学过的切片,还可以使用如下方法。
df.loc[行索引名称或条件[, 列索引名称]]
:基于标签索引,用于按标签名称或条件选取数据。当执行切片操作时,既包含起始索引,也包含结束索引。
emp_df.loc[0:2,["job","sal"]]
emp_df.loc[emp_df.sal>1500, ["ename","job","sal"]]
emp_df.loc[0:3,'mgr':'sal']
布尔选择
:对行数据可以使用条件进行过滤,多条件的逻辑运算符使用&
、|
、!=
、==
,并使用圆括号来明确指定条件的优先级,避免歧义。
emp_df.loc[(emp_df.sal>1500) & (emp_df.sal<3000), ["ename","sal","job"]]
emp_df[(emp_df.sal>1500) &(emp_df.sal<3000)][["ename","sal"]]
df.iloc[行索引位置,列索引位置]
:只能使用整数索引,不能使用标签索引来选取数据。当执行切片操作时,包含起始索引,也包含结束索引。
emp_df.iloc[2:5, 2:5]
df.query(expr, inplace=False):使用类似于SQL的表达式筛选数据,并返回筛选后的结果,注意在使用的列名中的空格要用
_`替换,字段名区分大小写且等于判断必须使用双等号。expr
: 字符串形式的SQL表达式,用于过滤数据。inplace
: 如果是的话,在原始数据框中进行修改
emp_df.query("sal>1500 and job=='MANAGER'")
data.columns =[column.replace(" ", "_") for column in data.columns]
把列名中的空格替换为下划线
函数应用与映射
在数据分析时,经常会对数据进行较复杂的运算,此时需要定义函数,定义好的函数可以应用到Pandas,数据中,有三种方法可以实现。
-
map
,将函数套用到Series的每个元素中。参数可以传递字典,进行指定数据1对1映射替换。 -
apply
,将函数套用到DataFrame的行与列上,行与列通过axis参数设置。也可以作用于Series上,效果比map好。 -
applymap
,将函数套用到DataFrame的每个元素上。
排序
在数据处理中,数据的排序也是常见的一种操作。由于Pandas中存放的是索引和数据的组合,索引它既可以按索引进行排序,也可以按数据进行排序。
df.sort_index(axis=0,ascending=True,inplace=False):
按索引排序,该方法可以用行索引或者列索引进行排序。axis
:轴索引,0表示index,即按行排序;1表示columns,即按列排序。ascending
:是否升序排列,默认为True,表示升序。inplace
:表示对数据进行排序,不创建新的实例。
df.sort_values(by,axios=0,ascending=True,inplace=False,na_position='last')
:按值排序。by
:表示排序的列。np_position
:表示NaN的值放在开头(first
)还是最后(last
),默认是最后。
# DataFrame中指定列排序
emp_df.sort_values("sal",inplace=True)
# Series排序
emp_df.sal.sort_values(ascending=False)
数据聚合-aggregate
agg
、aggregate
方法都支持对每个分组应用某个函数,包括Python内置函数或自定义函数。同时,这两个方法也能直接对DataFrame进行函数应用操作。
df['sal'].agg(['sum','max','min','mean'])
df['sal'].agg([('总薪资','sum'),('平均薪资','mean')])
df['sal'].agg({'总薪资',np.sum,'平均薪资',np.mean})
# agg返回一个聚合分组
df[['deptno','sal']].groupby('deptno').agg(np.sum)
# agg返回两个聚合分组
result = df[['deptno','sal']].groupby('deptno').agg([np.sum,np.mean])
result.sal['sum']
# 自定义函数
def count(item):
return len(item)
emp_df.groupby('deptno')['sal'].agg([np.sum,np.max,np.mean,count])
分组运算-transform
agg
是将函数应用于每一列,返回分组后的聚合结果,而transform
方法可以将运算分布到每一行,类似于窗口函数,在求比例的时候比较有用。
emp_df.groupby('deptno')['sal'].agg(np.mean)
# 求每个员工薪资,占部门总薪资的百分比
result_df = emp_df.groupby('deptno')[['deptno','sal']].transform(np.sum)
result_df['emp_sal'] = emp_df['sal']
# # 求每个部门中员工薪资占部门总薪资的百分比
dept_total_sal = emp_df.groupby('deptno')['sal'].transform(np.sum)
emp_df['dept_total_sal'] = dept_total_sal
round(emp_df.sal / emp_df.dept_total_sal * 100,2).astype('string') + '%'
加减时间数据
时间数据的算术运算在现实中随处可见,例如,2020年1月1日减一天就是2019年12月31日。pandas的时间数据和现实生活中的时间数据一样可以做运算。这时就涉及Pandas的**Timedelta**
类。
Timedelta是时间相关类中的一个异类,不仅能够使用正数,还能够使用负数表示单位时间,如1s、2min、3h等。使用Timedelta类,配合常规的时间相关类能够轻松实现时间的算术运算。
在Timedelta类的时间周期中没有年和月,所有周期名称、对应单位及其说明如下表:
周期名称 | 单位 | 说明 | 周期名称 | 单位 | 说明 |
---|---|---|---|---|---|
weeks | 无 | 星期 | seconds | s | 秒 |
days | D | 天 | milliseconds | ms | 毫秒 |
hours | h | 小时 | microseconds | us | 微妙 |
minutes | m | 分 | nanoseconds | ns | 纳秒 |
pd.Timedelta("1 days") # Timedelta('1 days 00:00:00')
pd.Timedelta("1 days 2 hours") # Timedelta('-2 days +23:57:57')
pd.Timedelta(pd.offsets.Second(2)) # Timedelta('0 days 00:00:02')
pd.Timedelta(pd.offsets.Minute(-2)) # Timedelta('-1 days +23:58:00')
# 时间加减
result = music_df['date'] + pd.Timedelta("1 days")
result.head(3)
Pandas高级接口
Series对象和DataFrame的列数据提供了cat
、dt
、str
三种属性接口,分别对应分类数据、日期时间数据和字符串数据,通过这几个接口可以快速实现特定的功能,非常快捷。
.dt(日期时间数据)
.dt 属性主要用于处理日期时间数据。当你有一个包含日期时间对象的 Series 或 DataFrame 列时,你可以使用 .dt 访问器来执行各种日期和时间相关的操作,如提取年份、月份、日期、时间等。
pandas.to_datetime(date)
:将数据列表中的 Series 列转化为 datetime 类型。series.dt.strftime('%Y-%m-%d %H:%M:%S')
:将日期数据转换为指定格式的字符串。series.dt.date/year/month/day/hour/time/quarter/weekday
:提取日期类型数据的年 / 月 / 日 / 时 / 分 / 秒 / 季度 / 星期。
import pandas as pd
# 创建一个包含日期时间的Series
s = pd.Series(pd.date_range('2023-01-01', periods=5))
# 使用.dt属性提取年份
print(s.dt.year)
# 提取月份、日期等
print(s.dt.month)
print(s.dt.day)
dt常用方法
1. 提取日期时间组件
- dt.year:提取年份。
- dt.month:提取月份。
- dt.day:提取日期。
- dt.hour:提取小时(对于 datetime 对象)。
- dt.minute:提取分钟(对于 datetime 对象)。
- dt.second:提取秒(对于 datetime 对象)。
- dt.microsecond:提取微秒(对于 datetime 对象)。
2. 日期时间的格式化
- dt.strftime(date_format):将日期时间对象格式化为字符串。例如,df['date'].dt.strftime('%Y-%m-%d') 会将日期时间列格式化为 "YYYY-MM-DD" 的形式。
3. 日期时间的属性
- dt.date:返回日期时间对象的日期部分(只包含年月日)。
- dt.normalize():将日期时间对象规范化为午夜(00:00:00)。
- dt.time:返回日期时间对象的时间部分(只包含时分秒)。
4. 日期时间的计算和判断
- dt.weekday 或 dt.weekday_name:返回日期是星期几(0 表示星期一,6 表示星期日;或返回星期几的字符串名称)。
- dt.week 或 dt.weekofyear:返回日期是一年中的第几周。
- dt.dayofweek:返回日期是星期几(0 表示星期一,6 表示星期日,与 dt.weekday 相同,但返回的是整数)。
- dt.dayofyear:返回日期是一年中的第几天。
- dt.quarter:返回日期是第几季度(1 到 4)。
- dt.is_leap_year:判断年份是否为闰年。
- dt.is_month_start、dt.is_month_end、dt.is_quarter_start、dt.is_quarter_end、dt.is_year_start、dt.is_year_end:判断日期是否是一个月、季度或年的开始或结束。
5. 日期时间的算术运算
- 你可以对日期时间进行算术运算,如加法、减法,以调整日期时间。例如,df['date'] + pd.Timedelta(days=1) 会将日期时间列中的每个日期增加一天。
6. 时间差
- 你可以使用 dt.diff() 来计算两个连续日期时间之间的差异(返回一个包含时间差的 Series)。
.str(字符串数据)
.str 属性用于处理字符串数据。当你有一个包含字符串的 Series 或 DataFrame 列时,.str 访问器提供了许多用于字符串操作的便捷方法,如字符串切片、大小写转换、查找和替换等。
import pandas as pd
# 创建一个包含字符串的Series
s = pd.Series(['apple', 'banana', 'cherry', 'date'])
# 使用.str属性转换为小写
print(s.str.lower())
# 查找并替换字符串中的子串
print(s.str.replace('a', 'o'))
# 使用.str.contains检查是否包含某个子串
print(s.str.contains('a'))
str常用方法
1. 大小写转换
- str.lower(): 将字符串转换为小写。
- str.upper(): 将字符串转换为大写。
- str.capitalize(): 将字符串的首字母转换为大写,其余部分转换为小写。
- str.swapcase(): 反转字符串中所有字母的大小写。
2. 字符串的匹配和查找
- str.contains(pattern, [case=True], [na=nan], [regex=True]): 判断字符串是否包含指定的子串或正则表达式模式。
- str.startswith(pat, [na=nan]) 和 str.endswith(pat, [na=nan]): 判断字符串是否以指定的前缀或后缀开始或结束。
- str.find(sub[, start[, end]]) 和 str.rfind(sub[, start[, end]]): 查找子串在字符串中的位置,rfind从右向左查找。
3. 字符串的替换
- str.replace(pat, repl[, n=-1[, case=True[, regex=False[, flags=0]]]]): 替换字符串中的子串或正则表达式模式。
4. 字符串的分割和连接
- str.split(pat=None, n=-1, expand=False): 使用指定的分隔符将字符串分割为子串列表。
- str.rsplit(pat=None, n=-1, expand=False): 从右向左分割字符串。
- str.cat(others=None, sep=None, na_rep=None, join_axes=None): 连接多个字符串。
5. 字符串的切片和提取
- str.slice(start=None, stop=None, step=None): 提取字符串的子串(类似于Python的切片操作)。
- str.slice_replace(start=None, stop=None, repl=None): 替换字符串中指定范围的子串。
- str.get(i): 获取指定位置的字符(只能获取一个)。
- str.extract(pat, expand=None): 使用正则表达式从字符串中提取匹配项。
6. 字符串的修改和清理
- str.strip([to_strip]), str.lstrip([to_strip]), str.rstrip([to_strip]): 删除字符串两端、左侧或右侧的指定字符(默认为空白字符)。
- str.zfill(width): 使用零填充字符串的左侧,直到达到指定的宽度。
- str.pad(width, side='left', fillchar=' '): 在字符串的左侧、右侧或两侧填充指定的字符,直到达到指定的宽度。
- str.wrap(width, **kwargs): 将字符串在指定的宽度处换行。
- str.justify(width, mode='left', fillchar=' '): 对字符串进行对齐操作。
7. 字符串的长度和计数
- str.len(): 返回字符串的长度。
- str.count(pat, [start[, end]]): 返回子串在字符串中出现的次数。
8. 字符串的排序和比较
- str.sort_values(): 当在DataFrame中使用时,可以根据字符串列的值对行进行排序。
- str.compare(other, na_equality=None): 比较两个字符串对象是否相等。
数据清洗
数据清洗是一项复杂且繁琐的工作,同时也是整个数据过程中最为重要的环节。
数据分析的目的在于提高数据质量,将脏数据(没有实际意义、格式非法、不完整的、有噪声和不一致的数据)清洗干净,使原数据具有完整性、唯一性、权威性、合法性、一致性等特点。Pandas中常见的数据清洗操作有空值和缺失值的处理、重复值的处理、异常值的处理、统一数据格式等。
空值和缺失值的处理
一般空值使用None表示,缺失值使用NaN表示。Pandas中提供了一些用于检查或处理空值和异常值的函数,其中isnull
和notnull()
函数可以判断数据集中是否存在空值和缺失值,对于缺失数据可以使用dropna()
和fillna()
方法进行删除和填充。
Series/DataFrame.isnull()/pandas.isnull(obj)
:检查空值对象。一旦发现数据中存在NaN或None,则将这个位置标记为True,否则就标记为False。Series/DataFrame.notnull()/pandas.notnull(obj)
:检查非空值对象。一旦发现有空值或缺失值时返回False。DataFrame.any(axis=0)/DataFrame.all(axis=0)
:指定列或行中是否有指定数据或者全部数据。可配合空判断,检测所在行或列是否有空值。df.notnull().all(axis=1)
/df.isnull().any(axis=1) / df.loc[~(df.isnull().any(axis=1))]
:检测数据行中是否有缺失数据,~是取反
。indexs = df.loc[df.isnull().any(axis=1)].index``df.drop(labes=indexs, axis=0)
:drop开头的axis和其他类型的axis的取值刚好相反。
Series/DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
:删除含有空值或缺失值的行或列。axis
:确定过滤行或列,取值可以为0或index、1或columns,默认是0。how
:确定过滤的标准,取值可以为any表示如果存在则删除该行或列、all则需要所有值都是NaN,默认是any。thresh
:表示有效数据量的最小要求。若传入了2,则是要求该行或该列至少有两个非NaN值时将其保留。subset
:表示在特定的子集中寻找NaN。
Series/DataFrame.fillna(value=None, method=None, axis=None, inplace=False)
:填充空值或缺失值。- value:用于填充的数值。
- method:表示填充方式,默认值为None,取值有
pad/ffill
表示用缺失值的前面的一个值填充、backfill/bfill
表示缺失值后面一个值填充。注意:method参数不能与value参数同时使用。
# 测试数据
df = pd.DataFrame({"类别":['小说', '散文随笔', '青春文学', '传记'],
"书名":[np.nan, '《皮囊》', '《旅程结束时》', '《老舍自传》'],
"作者":["老舍", None, "张其鑫", "老舍"]})
# 空值和缺失值检测
pd.isnull(df["书名"]) # df.isnull()
pd.notnull(df["书名"]) # df.notnull()
df[pd.isnull(df["书名"])] # 获取书名为空的数据
df.isnull().all(axis=1) # 获取全部为空的行
df.isnull().any(axis=1).sum() # 含有缺失值的行有多少个
# 空值和缺失值删除
df.dropna(subset=['书名'])
# 空值和缺失值填充
df.fillna('未知') # 使用【未知】填充缺失值和空值
df.fillna({'书名':'《未知》','作者':'未知'}) # 指定具体列的填充数据
df.fillna(method='bfill') # 使用缺失值的后一个值填充
重复值的处理
当数据中出现了重复值,在大多数情况下需要进行删除。
Pandas提供了两个函数专门用来处理数据中的重复值,分别为duplicated()
和drop_duplicates()
方法。
duplicated(subset=None, keep='first', inplace=False)
:用于标记是否有重复值,只要两条数据中所有条目的值完全相等,就判断为重复值,标记为True。subset
:用于识别重复的列标签或列标签序列,默认识别所有的列标签。keep
:删除重复项并保留第一次出现的项,取值可以为first(除第一次出现外,其余相同的都标记重复)、last或False(所有相同的都标记为重复)。
drop_duplicates()
:用于删除重复值,判断标准与duplicated()
一致。Series.unique()
:去除重复元素Series.nunique()
:统计去重后的元素个数Series.value_counts()
:统计不同元素出现的次数Series.map({val1:val2,val3:val4})
:映射,把一个数据映射为另一个数据,返回一个新的Series列。参数可以是字典,也可以是lambda函数
df = pd.DataFrame({'id': [1, 2, 3, 4, 4, 5],
'name': ['小铭', '小月月', '彭岩', '刘华', '刘华', '周华'],
'age': [18, 18, 29, 58, 58, 36],
'height': [180, 180, 185, 175, 175, 178],
'gender': ['女', '女', '男', '男', '男', '男']})
df.duplicated(keep=False) # 检查是否有重复值,标记所有重复行
df.drop_duplicates(keep='first') # 删除后一个重复行
异常值的处理
异常值是指样本中的个别值,其数值明显偏离它所属样本的其余观测值。异常值的存在会严重干扰数据分析的结果,因此经常要检验数据中是否有输入错误或含有不合理的数据。在数据统计方法中一般常用散点图、箱线图等方式检测异常值。
df = pd.DataFrame(np.arange(20),columns=['X'])
df['Y'] = df['X'] * 1.5 + 2
df.iloc[3,1] = 48
df.iloc[18,1] = 40
df.plot(kind='scatter',x='X',y='Y',grid=True)
df = pd.DataFrame({'A':[1,2,3,4],
'B':[2,3,25,2],
'C':[1,4,7,4],
'D':[1,5,30,3]})
df.boxplot()
# 获取异常值
fig = df.boxplot(column='B',return_type='dict')
min = fig['caps'][0].get_ydata()[0] # 下界值
max = fig['caps'][1].get_ydata()[0] # 上界值
df[df['B'] > max]