修改索引
# 将索引重置为:0到(n-1)
df.reset_index(inplace=True,drop=True)
df.index = range(df.shape[0])
# 将sip这一列作为索引
# 修改后df.values中不会出现sip这一列的数据,df.columns也没有sip字段
df.set_index('sip',inplace=True)
# 添加drop参数,就能保留sip
df.set_index('sip',inplace=True.drop=False)
# 或者
df.set_index(df['sip'],inplace=True)
修改列名
# 修该全部 (注意列名是一一对应的,数量不能多也不能少)
df.columns=['省份','城市','区、县']
# 针对性修改 (可以是一个也可以是多个)
df.rename(columns={'省份':'省/直辖市/自治区','城市': '市/自治州'},inplace=True)
修改值
运算型修改
import pandas as pd
import numpy as np
matrix = np.arange(1,19).reshape(6,3)
df = pd.DataFrame(matrix,columns=list('xyz'),index=list('abcdef'))
print(df)
''' 为了方便样式,创建了一个全是数字的DataFrame
x y z
a 1 2 3
b 4 5 6
c 7 8 9
d 10 11 12
e 13 14 15
f 16 17 18
'''
计算整个DataFrame
# 将所有数值都加10
df = df.apply(lambda x:x+10)
df = df.applymap(lambda x:x+10)
# 或者
def get_sum(x):
return x+10
df = df.apply(get_sum)
# 或者
def getSum(x, y):
return x+y
df = df.apply(getSum, args=[10])
# 将所有数值都修改成它的平方
df = df.apply(lambda x:x*x)
df = df.applymap(lambda x:x*x)
df = df.apply(np.square)
# 或者
def get_squ(x):
return x**2
df = df.apply(get_squ)
计算指定行
# 将索引是a的行的数值都乘10(axis参数默认是0)
df.iloc[0,:] = df.iloc[0,:].apply(lambda i:i*10)
df.iloc[0] = df.iloc[0].apply(lambda i:i*10)
df.loc['a'] = df.loc['a'].apply(lambda i:i*10)
df.loc['a',:] = df.loc['a',:].apply(lambda i:i*10)
df = df.apply(lambda i:i*10 if i.name=='a' else i, axis=1)
# 将索引是c d的行的数值都乘10(axis参数默认是0)
df.iloc[[2,3],:] = df.iloc[[2,3],:].apply(lambda i:i*10)
df.iloc[[2,3]] = df.iloc[[2,3]].apply(lambda i:i*10)
df.loc[['c','d']] = df.loc[['c','d']].apply(lambda i:i*10, axis=1)
df.loc[['c','d'],:] = df.loc[['c','d'],:].apply(lambda i:i*10, axis=1)
df = df.apply(lambda i:i*10 if i.name in ['c','d'] else i, axis=1)
计算指定列
# 将x列的数值都加10
df['x'] = df['x'].apply(lambda i:i+10)
df = df.apply(lambda i:i+10 if i.name=='x' else i)
# 将x列的数值都乘2
df['x'] = df['x'].apply(lambda x:x*2)
df['x'] = df['x'].map(lambda x:x*2)
# 将x y列的数值都乘10(axis参数默认是0)
df[['x','y']] = df[['x','y']].apply(lambda i:i*10)
df.loc[:,['x','y']] = df[['x','y']].apply(lambda i:i*10)
df = df.apply(lambda i:i*10 if i.name in ['x','y'] else i)
替换型修改
# 以人的思维数,修改第三行,第二列的值
df.iloc[2, 1] = '你大爷'
# 修改索引是 18216720 ,列名是 分数 的值
df.loc['18216720', '分数'] = 100
# 替换调体重这列中的后缀千克,最后将数据转为数字型
df.loc[:,'weight'] = df['weight'].str.replace('千克','').astype('int32')
df['weight'] = df['weight'].map(lambda x: int(str(x).replace('千克','')))
df['weight'] = df['weight'].apply(lambda x: int(str(x).replace('千克','')))
替换数据类型
df = df.astype(
{
"date": "datetime64[ns]",
"price": "int",
"is_weekend": "bool",
"status": "category",
}
)
字符串处理
- 使用方法:先获取Series(比如 df[‘列名’] 这就是一个Series对象)的str属性,然后在属性上调用函数
- 只能在字符串列上使用,不能在数字列上使用
- DataFrame上没有str属性和处理方法
- Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似
print(df['name'].str)
<pandas.core.strings.accessor.StringMethods object at 0x000001DD2B61D0A0>
替换
返回一个Series
# 替换调体重这列中的后缀千克 dtype: object
data = df['weight'].str.replace('千克','')
# 替换调体重这列中的后缀千克,并将数据转为数字型 dtype: int32
data = df['weight'].str.replace('千克','').astype('int32')
实战应用
# 替换调体重这列中的后缀千克,并将数据转为数字型
df.loc[:,'weight'] = df['weight'].str.replace('千克','').astype('int32')
# 将时间 2021-10-10 替换为 20211010 替换后 dtype 依旧是 object
df['time'] = df['time'].str.replace('-','')
# 将时间 2021-10-10 替换为 2021年10月10日
def get_time(x):
year,month,day = x['time'].split('-')
return f'{year}年{month}月{day}日'
df['time'] = df.apply(get_time, axis=1)
# 将时间 2021年10月10日 替换为 20211010 替换后 dtype 依旧是 object
# 方法1,链式replace
df['time'] = df['time'].str.replace('年','').str.replace('月','').str.replace('日','')
# 方法2,正则表达式 (下面四个等效,警告都报一样)
df['time'] = df['time'].str.replace('[年月日]','')
df['time'] = df['time'].str.replace('[年|月|日]','')
df['time'] = df['time'].str.replace('年|月|日','')
df['time'] = df['time'].str.replace("['年','月','日']","")
处理缺失值
样例
import pandas as pd
df = pd.read_excel('F:\\data\\student_excel.xlsx', skiprows=2)
检测空值
isnull() 和 notnull() : 检测是否是空值
# 返回一个相同行列数的DataFrame,若对应位置有值,则显示False,若对应位置是空值,则显示True
isn = df.isnull()
# 与isnull()类似,但刚好相反。返回一个相同行列数的DataFrame,若对应位置有值,则显示True,若对应位置是空值,则显示False
notn = df.notnull()
# 也可以值针对其中一列
isnull_school = df['school'].isnull()
notnull_school = df['school'].notnull()
# 筛选出名字不空的行(列名必须有,loc参数需要一个Series形式的bool值,但不接受DataFrame形式的bool值)
name_notnull = df.loc[df['姓名'].notnull(), :]
删除空值
dropna() : 丢弃、删除缺失值
- axis:删除行还是列(0和index是行,1和columns是列,默认0)
- how:如果等于any则存在空值就删除,如果等于all则所有值都为空才删除
- inplace:如果为True则修改当前df,否则返回新的df
- subset:对指定列删除空值
# 删除存在空值的行 (下面两个一样)
df.dropna(inplace=True)
df.dropna(axis=0,how='any',inplace=True)
# 删除全是空值的行(下面三个一样)
df.dropna(how='all', inplace=True)
df.dropna(axis=0, how='all', inplace=True)
df.dropna(axis='index', how='all', inplace=True)
# 删除全是空值的列(下面两个一样)
df.dropna(axis=1, how='all', inplace=True)
df.dropna(axis='columns', how='all', inplace=True)
# 针对分数这列,删除值为空的行
df.dropna(subset=['分数'], inplace=True)
填充空值
fillna() : 填充空值
- value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
- method:等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill
- axis:按行还是列填充(0和index是行,1和columns是列,默认0)
- inplace:如果为True则修改当前df,否则返回新的df
# 对于DataFrame,空值全部填充为零
# df.fillna(value=0, axis=1, inplace=True) 因为是全部填充,所以axis取值不影响结果
df.fillna(0, inplace=True)
# 只针对分数这一列,空值全部填充为零(下面两个一样)
df.fillna({'分数':0}, inplace=True)
df.loc[:,'分数'] = df['分数'].fillna(0)
# 将姓名填充完整(下面两个一样,推荐第二个。axis只能指定为行)
df.fillna(axis=0, method='ffill', inplace=True)
df.loc[:,'姓名'] = df['姓名'].fillna(method='ffill')