文章目录
- 修改替换变量值
- 对应数值的替换
- 指定数值范围的替换
- 虚拟变量变换
- 数值变量分段
- 数据分组
- 基于拆分进行筛选
- 分组汇总
- 使用 agg 函数进行汇总
- 引用自定义函数
- 长宽格式转换
- 转换为最简格式
- 长宽型格式的自由互转
- 多个数据源的合并
- 数据的横向合并
- concat 命令
- 处理缺失值
- 认识缺失值
- 缺失值查看
- 填充缺失值
- 删除缺失值
- 数据查重
- 标识出重复的行
- 直接删除重复的行
修改替换变量值
本质上是如何直接指定单元格的问题,只要能准确定位单元地址,就能够做到准确替换。
# 判断哪一行是我们要的数据 先定位再给值
df.体重[1] = 78
df['体重'][1] = 68
df.loc[1,
'体重'] = 78
df.开设.isin(['不清楚'])
df.开设[df.开设.isin(['不清楚'])] = '可以'
对应数值的替换
df.replace(
to_replace = None :将被替换的原数值,所有严格匹配的数值
将被用 value 替换,可以是 str/regex/list/dict/Series/numeric/None
value = None :希望填充的新数值
inplace = False
)
df.开设.replace('可以','不清楚',inplace = True)
df.性别.replace(['女','男'],[0,1],inplace =True)
df.性别.replace({0:'女',1:'男'},inplace =True)
指定数值范围的替换
方法一:使用正则表达式完成替换
df.replace(regex, newvalue)
方法二:使用行筛选方式完成替换
用行筛选方式得到行索引,然后用 loc 命令定位替换目前也支持直接筛选出单元格进行数值替换
# 使用正则匹配数据
df.开设.replace(regex = '不.+',value = '可以',inplace = True)
#iloc loc
df.支出.iloc[0:3] = 20
df.支出.loc[0:2] =30
#条件筛选替换
df.体重[df.体重>70] =70
df[df.体重==70].体重 = 80 # 注意引用问题
#query()的使用
df.query('性别 == "女" and 体重 > 60 ').体重 =50
df.loc[df.query('性别 == "女" and 体重 > 60').体重.index,'体重'] = 50
虚拟变量变换
pd.get_dummies(
data :希望转换的数据框/变量列
prefix = None :哑变量名称前缀
prefix_sep = 11 :前缀和序号之间的连接字符,设定有prefix 或列名时生效
dummy_na = False :是否为 NaNs 专门设定一个哑变量列
columns = None :希望转换的原始列名,如果不设定,则转换所有符合条件的列
drop_first = False :是否返回 k-l 个哑变量,而不是 k 个哑变量
)
返回值为数据框
df2.head()
pd.get_dummies(df2.类型,prefix = '_' )
pd.get_dummies(df2 , columns= [ '类型' ])
数值变量分段
pd.cut(
X :希望逬行分段的变量列名称
bins :具体的分段设定
int :被等距等分的段数
sequence of scalars :具体的每一个分段起点,必须包括最值,可不等距
right = True :每段是否包括右侧界值
labels = None :为每个分段提供自定义标签
include_lowest = False :第一段是否包括最左侧界值,需要和right 参数配合
)
- 分段结果是数值类型为 Categories 的序列
- pd.qcut ——按均值取值范围进行等分
#按均值取值范围进行等分
df['cut1'] = pd.qcut(df.身高,q=5)
#自定义分段
df['cut2'] = pd.cut(df.身高,bins=[150,160,170,180,190],right=False)
数据分组
df.groupby(
by :用于分组的变量名/函数
level = None :相应的轴存在多重索引时,指定用于分组的级别
as_index = True :在结果中将组标签作为索引
sort = True :结果是否按照分组关键字逬行排序
)
- 生成的是分组索引标记,而不是新的 df
dfg = df.groupby ('开设')
#查看dfg里面的数据
dfg.groups
#查看具体描述
dfg.describe( )
#按多列分组
dfg2 = df.groupby(['性别','开设'])
dfg2.mean ()
基于拆分进行筛选
筛选出其中一组
dfgroup.get_group()
dfg.get_group ('不必要').mean ()
dfg.get_group ('不必要').std ()
筛选出所需的列
该操作也适用于希望对不同的变量列进行不同操作时
dfg['身高'].max()
分组汇总
在使用 groupby 完成数据分组后,就可以按照需求进行分组信息汇总,此时可以使用其它专门的汇总命令,如 agg 来完成汇总操作。
使用 agg 函数进行汇总
df.aggregate( )
- 名称可以直接简写为 agg
- 可以用 axis 指定汇总维度
可以直接使用的汇总函数
名称 | 含义 |
---|---|
count () | Nuniber of non-null observations size () group sizes |
sum() | Sum of values29 |
mean() | Mean of values |
median() | Arithmetic median of values |
min () | Minimum |
max() | Maximum |
std() | Unbiased standard deviation |
var () | Unbiased variance |
skew() | Unbiased skewness(3rd moment) |
kurt() | Unbiased kurtosis (4th moment) |
quantile () | Sample quantile (value at %) apply() Generic apply |
cov() | Unbiased covariance (binary) |
corr() | Correlation (binary) |
dfg.agg( 'count')
dfg.agg('median')
dfg.agg(['mean', 'median'])
dfg.agg(['mean', 'median'])
#引用非内置函数
import numpy as np
df2.身高.agg (np. sum)
dfg.身高.agg (np. sum)
引用自定义函数
# 使用自定义函数
def mynum(x:int) ->int:return x.min()
df2.身高.agg (mymean)
dfg.agg(mymean)
长宽格式转换
基于多重索引,Pandas 可以很容易地完成长型、宽型数据格式的相互转换。
转换为最简格式
df.stack(
level = -1 :需要处理的索引级别,默认为全部,int/string/list
dropna = True :是否删除为缺失值的行
)
- 转换后的结果可能为 Series
用法:
df =pd.read_excel('person.xlsx')
dfs = df.stack()
长宽型格式的自由互转
df.unstack(
level = -1 :需要处理的索引级别,默认为全部,int/string/list
fill_value :用于填充缺失值的数值
)
dfs.unstack (1)
dfs.unstack([0,1])
数据转置: df.T
多个数据源的合并
数据的横向合并
merge 命令使用像 SQL 的连接方式
pd.merge(
需要合并的 DF
left :需要合并的左侧 DF
right :需要合并的右侧 DF
how = ’ inner’:具体的连接类型
{left、right 、outer 、 inner、)
两个 DF 的连接方式
on :用于连接两个 DF 的关键变量(多个时为列表),必须在两侧都出现
left_on :左侧 DF 用于连接的关键变量(多个时为列表)
right_on :右侧 DF 用于连接的关键变量(多个时为列表)
left_index = False :是否将左侧 DF 的索引用于连接
right_index = False :是否将右侧 DF 的索引用于连接
)
left=pd.DataFrame({'key':['k0','k1','k2','k3'],'A':['A0','A1','A2','A3'],'B':['B0','B1','B2','B3'],})
right=pd.DataFrame({'key':['k0','k1','k2','k4'],'C':['C0','C1','C2','C3'],'D':['D0','D1','D2','D3'],})
left
'''key A B
0 k0 A0 B0
1 k1 A1 B1
2 k2 A2 B2
3 k3 A3 B3
'''
right
'''key C D
0 k0 C0 D0
1 k1 C1 D1
2 k2 C2 D2
3 k4 C3 D3
'''
# inner left right
# 内连接 只保留相同key的值
# 外连接 left 以左边的df为基准 保留所有的左边的所有同列名的值
# 全连接 outer 全连接
pd.merge(left,right,how='inner')
'''key A B C D
0 k0 A0 B0 C0 D0
1 k1 A1 B1 C1 D1
2 k2 A2 B2 C2 D2
'''
pd.merge(left,right,how='left')
'''key A B C D
0 k0 A0 B0 C0 D0
1 k1 A1 B1 C1 D1
2 k2 A2 B2 C2 D2
3 k3 A3 B3 NaN NaN
'''
pd.merge(left,right,how='right')
'''key A B C D
0 k0 A0 B0 C0 D0
1 k1 A1 B1 C1 D1
2 k2 A2 B2 C2 D2
3 k4 NaN NaN C3 D3
'''
pd.merge(left,right,how='outer')
'''key A B C D
0 k0 A0 B0 C0 D0
1 k1 A1 B1 C1 D1
2 k2 A2 B2 C2 D2
3 k3 A3 B3 NaN NaN
4 k4 NaN NaN C3 D3
'''
concat 命令
同时支持横向合并与纵向合并
pd.concat(
objs :需要合并的对象,列表形式提供
axis = 0 :对行还是对列方向逬行合并(0 index 、 1 columns )
join = outer :对另一个轴向的索引值如何进行处理(inner 、outer )
ignore_index = False
keys = None :为不同数据源的提供合并后的索引值
verify_integrity = False : 是否检查索引值的唯一性,有重复时报错
copy = True
)
【示例】一维的Series拼接
ser1=pd.Series([1,2,3],index=list('ABC'))
ser2=pd.Series([4,5,6],index=list('DEF'))
pd.concat([ser1,ser2])
'''
A 1
B 2
C 3
D 4
E 5
F 6
dtype: int64
'''
【示例】df对象拼接
def make_df(cols,index):data={c:[str(c)+str(i) for i in index] for c in cols}return pd.DataFrame(data,index=index)
df1=make_df('AB',[1,2])
df2=make_df('AB',[3,4])
df1
'''A B
1 A1 B1
2 A2 B2
'''
df2
'''A B
3 A3 B3
4 A4 B4
'''
pd.concat([df1,df2])
'''A B
1 A1 B1
2 A2 B2
3 A3 B3
4 A4 B4
'''
【示例】两个df对象拼接,如果索引重复
x=make_df('AB',[1,2])
y=make_df('AB',[1,2])
x
'''A B
1 A1 B1
2 A2 B2
'''
y
'''A B
1 A1 B1
2 A2 B2
'''
pd.concat([x,y])
'''A B
1 A1 B1
2 A2 B2
1 A1 B1
2 A2 B2
'''
pd.concat([x,y],ignore_index=True)
'''A B
0 A1 B1
1 A2 B2
2 A1 B1
3 A2 B2
'''
pd.concat([x,y],keys=list('xy'))
'''A B
x 1 A1 B12 A2 B2
y 1 A1 B12 A2 B2
'''
【示例】两个df对象拼接,join参数的使用
a=make_df('ABC',[1,2,3,4])
b=make_df('BCD',[3,4,5])
a
'''A B C
1 A1 B1 C1
2 A2 B2 C2
3 A3 B3 C3
4 A4 B4 C4
'''
b
'''B C D
3 B3 C3 D3
4 B4 C4 D4
5 B5 C5 D5
'''
pd.concat([a,b],join='outer',axis=1)
'''A B C B C D
1 A1 B1 C1 NaN NaN NaN
2 A2 B2 C2 NaN NaN NaN
3 A3 B3 C3 B3 C3 D3
4 A4 B4 C4 B4 C4 D4
5 NaN NaN NaN B5 C5 D5
'''
a=make_df('ABC',[1,2])
b=make_df('BCD',[3,4])
pd.concat([a,b],join='inner')
'''B C
1 B1 C1
2 B2 C2
3 B3 C3
4 B4 C4
'''
处理缺失值
认识缺失值
系统默认的缺失值 None 和 np. nan
data=pd.Series([3,4,np.nan,1,5,None])
df=pd.DataFrame([[1,2,None],[4,np.nan,6],[5,6,7]])
'''0 1 2
0 1 2.0 NaN
1 4 NaN 6.0
2 5 6.0 7.0
'''
缺失值查看
直接调用info()方法就会返回每一列的缺失情况。
df.info()
'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 0 3 non-null int64 1 1 2 non-null float642 2 2 non-null float64
dtypes: float64(2), int64(1)
memory usage: 200.0 bytes
'''
Pandas中缺失值用NaN表示,从用info()方法的结果来看,索引1这一列是1 2 non-null float64,表示这一列有2个非空值,而应该是3个非空值,说明这一列有1个空值。
还可以用isnull()方法来判断哪个值是缺失值,如果是缺失值则返回True,如果不是缺失值返回False。
- df.isna(): 检查相应的数据是否为缺失值 同 df.isnull()。
- df.notna()等同于notnull()
【示例】获取所有缺失值
data=pd.Series([3,4,np.nan,1,5,None])
print('isnull()方法判断是否是缺值:')
print(data.isnull())
print(data.isna())
print('获取缺值:')
print(data[data.isnull()])
print('获取非空值')
print(data[data.notnull()])
填充缺失值
调用fillna()方法对数据表中的所有缺失值进行填充,在fillna()方法
中输入要填充的值。还可以通过method参数使用前一个数和后一
个数来进行填充。
df.fillna(
value :用于填充缺失值的数值,也可以提供dict/Series/DataFrame 以进—步指明
哪些索引/列会被替换 不能使用 list
method = None :有索引时具体的填充方法,向前填充,向后填充等
limit = None :指定了 method 后设定具体的最大填充步长,此步长不能填充
axis : index (0), columns (1)
inplace = False
)
【示例】Series对象缺失值填充
data=pd.Series([3,4,np.nan,1,5,None])
print('以0进行填充:')
print(data.fillna(0))
print('以前一个数进行填充:')
print(data.fillna(method='ffill'))
print('以后一个数进行填充:')
print(data.fillna(method='bfill'))
print('先按前一个,再按后一个')
print(data.fillna(method='bfill').fillna(method='ffill'))
【示例】DataFrame对象缺失值填充
df=pd.DataFrame([[1,2,np.nan],[4,np.nan,6],
[5,6,7]])
print('使用数值0来填充:')
print(df.fillna(0))
print('使用行的前一个数来填充:')
print(df.fillna(method='ffill'))
print('使用列的后一个数来填充:')
print(df.fillna(method='bfill' ,axis=1))
【示例】列的平均值来填充
df=pd.DataFrame([[1,2,np.nan],[4,np.nan,6],
[5,6,7]])
for i in df.columns:df[i]=df[i].fillna(np.nanmean(df[i]))
df
删除缺失值
调用dropna()方法删除缺失值,dropna()方法默认删除含有缺失值的行,也就是只要某一行有缺失值就把这一行删除。如果想按列为单位删除缺失值,需要传入参数axis=’columns’。
df.dropna(
axis = 0 : index (0), columns (1)
how = any : any、all
any :任何一个为 NA 就删除
all :所有的都是 NA 删除
thresh = None :删除的数量阈值,int
subset :希望在处理中包括的行/列子集
inplace = False
)
【示例】删除缺失值
df=pd.DataFrame([[1,2,np.nan],[4,np.nan,6],[5,6,7]])
print('默认为以行为单位剔除:')
print(df.dropna())
print('以列为单位剔除:')
df.dropna(axis='columns')
【示例】删除空白行
df=pd.DataFrame([[1,2,np.nan],[4,np.nan,6],[5,6,7]])
print('所有为nan时候才剔除:')
print(df.dropna(how='all'))
print('默认情况,只要有就剔除')
print(df.dropna(how='any'))
数据查重
标识出重复的行
标识出重复行的意义在于进一步检査重复原因,以便将可能的错误数据加以修改。
Duplicated
df['dup' ] = df.duplicated( ['课程','开设'])
利用索引进行重复行标识
df.index.duplicated()
df2 = df.set_index ( ['课程','开设'] )
df2.index.duplicated ()
直接删除重复的行
drop_duplicates (
subset=“ ”按照指定的行逬行去重
keep=‘first’ 、 ‘last’ 、 False 是否直接删除有重复的所有记录
)
df. drop_duplicates ( ['课程', '开设' ] )
df. drop_duplicates ( ['课程', '开设' ] , keep= False )
利用査重标识结果直接删除
df[~df.duplicated( )]
df[~df . duplicated ( ['课程', '开设' ] )]