数据分析-pandas数据处理清洗常用总结

利用pandas包进行数据分析时常见的操作有:

  • 1.创建对象
  • 2.查看对象
  • 3.选择
  • 4.缺失值处理
  • 5.相关操作
  • 6.合并
  • 7.分组和分段
  • 8.轴转换和数据透视表
  • 9.时间序列
  • 10.导入和保存数据

一、创建对象

  • 创建Series
  • 创建DataFrame
  • 查看不同列的数据类型
  • 改变索引列名
    1.通过传递一个 list 对象来创建一个 Series
s=pd.Series([1,2,3,np.nan,6,8])
s

11098258-6ef1a293a1d41ae4.png

2.通过传递一个 numpy array,时间索引以及列标签来创建一个 DataFrame
numpy.random.randn()是从标准正态分布中返回一个或多个样本值。
numpy.random.rand()的随机样本位于[0, 1)中。
np.random.randint(0,7,size=10)生成0到7的随机整数

dates=pd.date_range('20130101',periods=6)
df=pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
df
11098258-3d1c7f17ba01a58a.png

index和columns也可以在DataFrame创建后指定:

df.index=pd.date_range('20130101',periods=df.shape[0])
df.index=pd.date_range('20130101',periods=len(df))

另外,还可以指定某一列为索引

df = df.set_index('A', drop = True)

通过字典对象来创建一个 DataFrame

df2=pd.DataFrame({'A':1.,
                 'B':pd.Timestamp('20130102'),
                 'C':pd.Series(1,index=list(range(4)),dtype='float32'),
                 'D':np.array([3]*4,dtype='float32'),
                 'E':pd.Categorical(['test','train','test','train']),
                 'F':'foo'})
df2
11098258-3dbfd751a746f806.png

另外,在原有数据df的基础上,可以创建一个新的数据框df3

df3=pd.dataframe()
df3['min']=df.min()
df3['max']=df.max()
df3['std']=df.std()
df3

或者按行进行汇总统计创建一个新的数据框df4

df4=pd.dataframe()
df4['min']=df.min(axis=1)
df4['max']=df.max(axis=1)
df4['std']=df.std(axis=1)
df4

轴为0的时候是对列的数据进行统计运算,比如shape[0]是行的个数,相当于一个完整的列有多少数据,df.min(axis=0),求每一列的最小值。轴为1是对行的数据量进行统计。
3.查看不同列的数据类型

df2.dtypes
11098258-b4e49590ad3bd339.png

4.改变索引列名

df.rename(index=lambda x:x+5,columns={'A':'newA','B':'newB'})
11098258-54c4d41724bd9111.png

二、查看数据

  • 查看头尾的行数据
  • 显示索引、列、底层的数据
  • 统计
  • 转置
  • 按轴排序
  • 按值排序
  • 查看最大值的索引
  • 格式化输出format
    1.查看头尾的行数据
df.head()
11098258-ddf2be8ed8445481.png
df.tail(3)

11098258-391e974690f0719f.png

2.显示索引、列、底层的数据
df.index
df.columns
df.values
11098258-ec897723f89ed4c3.png

11098258-fef98ae782bb60c1.png

11098258-e84881d0350401ad.png

注意, list(df)显示的是columns
3.统计
查看数据框的行数与列数:(shape[0]是行数shape[1]是列数)

df.shape
11098258-aff0cf967b78e96d.png

查看数据框 (DataFrame) 的索引、数据类型及内存信息:

df.info()
11098258-a9ee416da47cae02.png

统计每一列非空个数

t.count()
11098258-bc5e91679f98f812.png

统计某列有多少个不同的类用.nunique()或者len(set()),(统计某列不同类对应的个数用value_counts(),后面相关操作中会提到)

df.A..nunique()
len(set(df.A))

统计某列有哪些不同的类(使用value_counts()也可以显示,同时会显示各个类的个数)

df.A.unique()

统计某列是否有重复数据

df.A.is_unique

对于数据类型为数值型的列,查询其描述性统计的内容:

df.describe()
11098258-a03b5213487a2102.png

统计相关系数

df.corr()

4.转置

df.T
11098258-0c06bf6295eab111.png

5.按轴排序
df.sort_index(0) 按行名排序
df.sort_index(1) 按列名排序

df.sort_index(axis=1,ascending=False)
11098258-b4f887e23e10460d.png

6.按值排序
按行的值排序:

df.sort_values(by='20130101',axis=1)
11098258-61d53ca74b3a71d5.png

按列的值排序:

df.sort_values(by='B')
11098258-ff2afbf83d8aeeec.png

按顺序进行多列降序排序

df.sort_values(['A','B'],ascending=False)

7.查看最大值的索引

df.idxmax(0)    #显示所有列最大值所对应的索引
df.A.idxmax(0)   #显示A列中最大值对应的索引

8.格式化输出format
“格式限定符”(语法是'{}'中带:号),可以print相应格式的数据

print('{:.2%}'.format(0.12354))
11098258-2068921ff3a80e8d.png

金额千位分隔符

print('{:,}'.format(123456789))
11098258-e12195b27c5a8caf.png
print('{:.2f}'.format(31.31412))
11098258-26221a53d11db003.png

三、选择

  • 直接获取数据
  • 通过标签进行选择 .loc[]
  • 通过位置进行选择 .iloc[:,:]
  • 布尔索引
  • 设置赋值
    1.直接获取数据(用于获取整行或者整列的数据),此处注意列名一定要大小写对应,否则无法取出数据
df['B']
df.B
11098258-1ab62fbc51eb7185.png

选择两列

df[['A','B']]

通过切片获取数据

df[0:3]
df['20130101':'20130103']
11098258-3fd36c51ce1cfa59.png

2.通过标签进行选择 .loc[]
标签的优点是可以多轴交叉选择(注意:iloc内部只能单独使用行标签选择行数据,选择某一列标签时前面需加:,):

df.loc[dates[0]]
11098258-c8b50d1618309899.png

位置加标签(注意只能用:,不能使用类似0:2的切片):

df.loc[:,['A','B']]
11098258-156b0540e24fd517.png

标签加标签:

df.loc['20130101',['A','B']]
11098258-31c323c928e13f83.png

获取一个标量:

df.loc['20130101','A']

11098258-a457479599c15427.png

3.通过位置进行选择 .iloc[:,:]
通过传递数值进行位置选择(选择的是行),特别是选择单行的时候(注意: iloc内部只有一个值得时候是选择的行,选择某一列时列号前面需加:,),另外-1代表最后一列:

df.iloc[3]
11098258-79b6777cbc528d4b.png

选取除了最后三列之外的数据

df.lioc[:,:-3]

通过数值进行切片 位置加位置(区别于loc之处)

df.iloc[1:3,1:3]
11098258-64b5bb8cf657b381.png

通过制定一个位置的列表:

df.iloc[[1,2],[2,3]]
11098258-458b523a4aa66739.png

对行、列进行切片:

df.iloc[[0,1],:]
df.iloc[:,[0,1]]
11098258-0cce1f804822907a.png

11098258-cec2bb3fd161eb76.png

获取特定的值:

df.iloc[1,1]
11098258-d2716c64090d3221.png

4.布尔索引
使用一个单独列的值来选择数据:

df[df.A>0]
11098258-40405d259c85eddc.png
df[df>0]
11098258-5251e9d0efa6a16f.png

选择A列中以a开头的行或列(假设此处的A列是字符串型数据)

df[df.A.str.startswith('a')]

使用 isin()方法来过滤:

df['E']=['one','one','two','there','four','there']
df[df.E.isin(['two','four'])]
11098258-749c75324f558da6.png

5.赋值
①通过标签设置新的值

df.loc['20130101','A']=1
df
11098258-6b446363275cef32.png

如果赋值的标签不存在,则产生新的列(行),未赋值的位置用空值填充

t.loc['20130101','H']=3
t
11098258-b33d6e2da5c9c664.png

②通过位置设置新的值

df.iloc[0,0]=2
df
11098258-0bcab0b63ccb56fb.png

③设置整列值(len可以求表格数据的行数):

df.loc[:,'D']=np.array([3]*len(df))
df

或者

df['D']=np.array([3]*len(df))
df
11098258-67a82f1b90e35650.png

④通过布尔索引赋值

df2=df.copy()
df2[df2>0]=-df2
df2     #全部转化为负数
11098258-68f1a75e37f67939.png

四、缺失值处理

  • 删除列的方法
  • 去掉包含缺失值的行,不改变原来的值
  • 对缺失值进行填充
  • 对数据进行布尔填充


    11098258-a9bd27b5b55ca832.png

    查看每一列有多少缺失值:

df.isnull().sum()

查看每一列有多少完整的数据

df.shape[0]-df.isnull().sum()

1.删除列的方法:

df.drop(df.columns[4],axis=1,inplace=True)  #不知道列名时
df.drop(‘E’,axis=1,inplace=True)   #根据列名删除

del df['E']

2.去掉包含缺失值的行,不改变原来的值

df.dropna()   #不返回df还是原值
df.dropna(how='all')   #删除所有均为空值的行
df.dropna(inplace=True)   #返回删除后的
11098258-10f493cc0e11f798.png

移除数据框 DataFrame 中包含空值的列

df.dropna(axis=1)
11098258-34860fca3290e17f.png

3.对缺失值进行填充(如果填充后需要保存,需加inplace=True):

df.fillna(value=5)
11098258-6b1935e040c7946e.png

将所有空值替换为平均值

df.fillna(df.mean())
11098258-cedf840ded3ce8c3.png

4.对数据进行布尔填充

pd.isnull(df)
11098258-d3f7112dc26f486b.png

五、相关操作

  • 统计行列平均值
  • Apply – 对数据应用函数
  • 计数 value_counts()
  • 字符串大小写转换
  • 数据类型转换
  • 替换
    1.统计行列平均值
    按列统计平均
df.mean()
11098258-4cb7fe9cc4d59109.png

对平均值取整

round(df.mean())

按行统计平均

df.mean(1)

11098258-5e558257cede72a5.png

2.Apply – 对数据应用函数
其中注意临时函数 lambda的使用

df.apply(lambda x:x.max()-x.min())
11098258-901f4819ffbfc2dd.png
df.apply(np.mean)   按行统计axis=1
11098258-af87fcbe6c1c6a4f.png
df.apply(np.max,axis=1)
11098258-cacd94df20e6bf49.png

另外可以通过def 定义函数,再使用apply,例如下面数据的第一列,时间为2061年,存在明显错误,可以通过创建函数去修复这个错误

data = pd.read_table(path6, sep = "\s+", parse_dates = [[0,1,2]]) 
data.head()
11098258-d9a65cc15a0164e9.png
import datetime
def fix_century(x):
    year = x.year - 100 if x.year > 1989 else x.year
    return datetime.date(year, x.month, x.day)
data['Yr_Mo_Dy'] = data['Yr_Mo_Dy'].apply(fix_century)
data.head()
11098258-369359fbe93639e3.png

3.计数 value_counts()

s=pd.Series(np.random.randint(0,7,size=10))
s.value_counts()
11098258-6c0c96c9d39043ba.png

DataFrame查看某一列类别数据各类的个数:

df2.E.value_counts()
11098258-e2e190e9822eaabd.png

DataFrame查看所有列的各类统计个数

df2.apply(pd.Series.value_counts)
11098258-89745cd19517696d.png

4.字符串大小写转换

s=pd.Series(['One','Two'])
s.str.lower()
11098258-b0231b9052b7e2a8.png

5.将DataFrame的格式转化为浮点数

df.astype(float)
11098258-6efaf2f9314c9b3d.png

6.替换

df.replace(4,'one')
11098258-ee3d0ca116769217.png

六、合并

  • concat (不通过键值之间的连接)
  • merge 类似于 SQL 类型的连接( join)☆
  • Append ---- 类似于 SQL 中 union
    1.concat (默认上下连接,axis=1时左右连接)
df=pd.DataFrame(np.random.randn(10,4))
df
11098258-7870d175bf573b40.png
pieces=[df[:1],df[6:7]]
pd.concat(pieces)

11098258-b7befe2e10f289e0.png

2.merge 类似于 SQL 类型的连接( join)
根据 连接
merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并

left=pd.DataFrame({'key':['foo','foo1'],
                  'lval':[1,2]})
left
11098258-b158d4f97eb6b368.png
right=pd.DataFrame({'key':['foo','foo2'],
                  'rval':[4,5]})
right
11098258-e210038b9e217fdb.png
pd.merge(left,right,on='key')
11098258-2fa427f27a2092d4.png

左连接left,右连接right,外连接outer 默认是inner

pd.merge(left,right,on='key',how='left')
11098258-f39dbcbde4e8acf6.png

3.Append 将一行连接到一个 DataFrame 上
专门用于上下按照同列名连接---- 类似于 SQL 中 union
append是concat的简略形式,只不过只能在axis=0上进行合并

df=pd.DataFrame(np.random.randn(5,4),columns=list('ABCD'))
df
11098258-7826a8f8234df01b.png
s=df.iloc[1,:]
df.append(s,ignore_index=True)
11098258-8cf68fcc854007ea.png

七、分组和分段

  • 分组(对数据进行分组汇总统计,类似数据透视表)
  • 通过多个列进行分组形成一个层次索引
  • 分段(对数据进行分段或者分箱切割,可用于连续变量的特征处理,例如woe)
df=pd.DataFrame({'A':['foo','bar','foo','bar','foo','bar','foo','bar'],
                'B':['one','two','three','four','two','two','one','three'],
                'C':np.random.randn(8),
                'D':np.random.randn(8)})
df
11098258-f659b846f9d3e4f7.png

1.分组,并对每个分组执行 sum/count/mean/median(中位数)等函数

df.groupby('A').sum()
df.groupby('A').agg(np.sum)
df.groupby('A').agg({'C':sum,'D':sum})
11098258-2c3fe1b3fac4b41b.png

分组求平均值、最大值、最小值

df.groupby('A').C.agg(['mean','max','min'])

按A中类的个数对C求平均值

df.groupby('A').agg({'C':sum})['C'].mean()

2.通过多个列进行分组形成一个层次索引

df.groupby(['A','B']).sum()
11098258-888afa1e4a18e1a0.png

3.分段(分箱)
有两种:pd.qcut与pd.cut
按变量取值范围进行均匀分割cut

cut11=pd.cut(df1["可用额度比值"],4)
cut11.head()
11098258-581ed261e1961924.png

按变量个数进行均匀分割qcut

cut11=pd.qcut(df1["可用额度比值"],4)
cut11
11098258-f0ae51de39d5fcd6.png
cut11=pd.qcut(df1["可用额度比值"],4,labels=False)
cut11.head()
11098258-f2ee9f6cd65d1a78.png

八、轴转换和数据透视表

  • Stack堆栈
  • 数据透视表
    1.Stack堆栈
tuples=list(zip(*[['bar','bar','baz','baz','foo','foo','qux','qux'],['one','two','one','two','one','two','one','two']]))
index=pd.MultiIndex.from_tuples(tuples,names=['first','ssecond'])
df=pd.DataFrame(np.random.randn(8,2),index=index,columns=['A','B'])
df
11098258-966f9e3422d82cb1.png
stacked=df.stack()
stacked
11098258-46bbc3ac1ea1b09c.png
stacked2=stacked.unstack()
stacked2
11098258-0f0439af340b1dab.png
stacked3=stacked2=stacked.unstack(0)
stacked3
11098258-9df67b7c7d49bd83.png
stacked4=stacked2=stacked.unstack(1)
stacked4

11098258-79f74b8ce1850990.png

2.数据透视表
pd.pivot_table()

df=pd.DataFrame({'A':['one','one','two','three']*3,
                'B':['A','B','C']*4,
                'C':['foo','foo','foo','bar','bar','bar']*2,
                'D':np.random.randn(12),
                'E':np.random.randn(12)})
df
11098258-e1e4dca24c42c677.png
pd.pivot_table(df,values='D',index=['A','B'],columns='C')
11098258-19d90e08d411636c.png
df.pivot_table(df,index=['A','B'],columns=['C'],aggfunc=np.sum)
11098258-ae7f516d73ed12fc.png

九、时间序列

  • 针对时间频率重采样
  • 时间类型转换
  • 时间采样分组
  • 时间筛选问题
    1.针对时间频率重采样
    首先创建一个采样后的时间序列:
rng=pd.date_range('20120101',periods=61,freq='S')
rng

11098258-550959ea4e7a8a0a.png

序列或者索引为时间时,可以使用 .resample()重置采样频率

ts=pd.Series(np.random.randint(0,500,len(rng)),index=rng)
ts.resample('1Min',how=sum)
11098258-fd61ebaa013fbdc6.png

另外采样频率还有:
W weekly frequency
M 每月最后一天
BM 每个月最后一个工作日
2.将int64型数据转化成datetime数据

crime.info()
crime.head()
11098258-7fa3b3792cc700a6.png
11098258-7f2edb6e3b3e40e8.png
crime.Year = pd.to_datetime(crime.Year, format='%Y')
crime.info()
crime.head()
11098258-28bf0121e33dcb56.png

11098258-34379a72b249ddf6.png

3.按时间采样结果分组
例如我们获得一组数据索引是每一年


11098258-01de68dd7db816cc.png

按如果想按十年进行分组查看数据情况,即进行时间分组求和,可以使用重采样
crimes = crime.resample('10AS').sum()

另外,人口不能按十年的直接相加,使用10年内的最大值汇总,在上述基础上更新population列

population = crime['Population'].resample('10AS').max()
crimes['Population'] = population
11098258-0d0a5bbdb74b7164.png

4.时间筛选问题
通过创建时间分列字段,进行取样统计计算,此方法优点是配合query可以实现灵活取样
例如,如下,计算每一列一月份的平均值


11098258-5296a8030195e6af.png

可以先将时间字段分列,相当于创建了辅助列

data['date'] = data.index
data['month'] = data['date'].apply(lambda date: date.month)
data['year'] = data['date'].apply(lambda date: date.year)
data['day'] = data['date'].apply(lambda date: date.day)
data.head()
11098258-23edb14050d8a1ca.png

再筛选计算

january_winds = data.query('month == 1')
january_winds.loc[:,'RPT':"MAL"].mean()
11098258-6cb8c9b0bc09bb04.png

按年进行取样

data.query('month == 1 and day == 1')
11098258-f2403adeec4c1a11.png

按月取样

data.query('day == 1')
11098258-a71abd2904349a5a.png

时间差,两个日期之间可以相减,并求对应月数和天数

(data.max() - data.min()).days

十、导入和保存数据

  • CSV
  • Excel
    1.导出
df.to_csv('foo.csv')
df.to_excel('foo.xlsx')
df.to_sql(table_name,connection_object) # 将数据框 (DataFrame)中的数据导入SQL数据表/数据库中
df.to_json(filename) # 将数据框 (DataFrame)中的数据导入JSON格式的文件中

2.导入:

pd.read_csv('foo.csv')
pd.read_excel('foo.xlsx')
pd.read_sql(query, connection_object) # 导入SQL数据表/数据库中的数据
pd.read_json(json_string) # 导入JSON格式的字符,URL地址或者文件中的数据

另外一种常用导入方式

path3 ='../input/pandas_exercise/exercise_data/drinks.csv'    #'drinks.csv'
drinks = pd.read_csv(path3)

3.文件导入参数
在读取文件时考虑到格式问题,会使用一些参数进行调整。
参考:https://www.cnblogs.com/datablog/p/6127000.html

sep指定分隔符。如果不指定参数,则会尝试使用逗号分隔。
其中,会用到正则表达式,可以参考:https://baike.baidu.com/item/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1700215?fr=aladdin
\s ->匹配任何空白字符,包括空格、制表符、换页符等
\f -> 匹配一个换页
\n -> 匹配一个换行符
\r -> 匹配一个回车符
\t -> 匹配一个制表符
\v -> 匹配一个垂直制表符
+->匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。
“\s+”则表示匹配任意多个上面的字符。

data = pd.read_table(path6,sep = '\s+') 
data.head()

11098258-26cb05531d08d78c.png

parse_dates 可以将指定的列转化为时间

data = pd.read_table(path6, sep = "\s+", parse_dates = [[0,1,2]]) 
data.head()
11098258-41e1a3bb7e53d168.png

猜你喜欢

转载自blog.csdn.net/weixin_34413357/article/details/87429969