Python数据分析师2020特训营-Pandas DataFrame 3

Python数据分析师2020特训营-Pandas DataFrame 3

DataFrame

数据整合

1
数据整合又称数据合井,将不同的数据合并在一起,这样可以将不同的信息集成在一张表上,有利于之后的分析
1
常见的合并方法有堆叠和按主键进行合井,堆叠又分为横向堆叠和纵向堆叠,按主键合并类似于sql里面的关联操作

堆叠concat

1
2
3
4
5
横向堆叠特两张表或多张表在X轴方向,即横向拼接在一起
纵向堆叠将两张表或多张表在Y轴方向,即纵向拼接在一起

注意使用concat时,axis=1用于横向,0代表纵向(默认为0)
注意join取inner或者outer时:分别代表交集和并集
横向堆叠
1
2
3
data=pd.concat([df1,df2],axis=1,join='inner') # 按行标签取交集,行标签需要一样

data=pd.concat([df1,df2],axis=1,join='outer') # 行标签一样的连接在一起,另外的类似sql全外连接
纵向堆叠
1
2
3
4
适合各表数据意义一样,每一列名字一样和顺序一样的
data=pd.concat([df1,df2],axis=0,ignore_index=False) # 标签值不一定唯一

data=pd.concat([df1,df2],axis=0,ignore_index=True) # 显式标签设置成了隐式标签 唯一

.merge

[数据分析 Pandas学习-DataFrame]

层级索引

[数据分析 Pandas学习-DataFrame]

数据排序

[数据分析 Pandas学习-DataFrame]

分组聚合

[数据分析 Pandas学习-DataFrame]

透视图和交叉表

1
在数据分析中,数据透视表是常见的工具之一,需要根据行或列对数据进行各个维度数据的汇总,在pandas中,提供了相关函数解决此类问题

透视图 pivot_table

透视图参考

1
跟Excel透视图一个道理
1
2
3
4
5
6
7
8
9
10
pd.pivot_table(data,index,columns,value,aggfun,fill_value,margins,margins_name)

index 行分组键(作为行索引)
columns 列分组键(作为列索引)
values 分组字段(需要汇总计算的列,可多选),只能为数值型变量
aggfunc 聚合函数
margins 是否需要总计
margins_name 总计名
fill_value 空缺值处理
dropna:默认为True,如果列的所有值都是NaN,将不作为计算列,False时,被保留
不指定columns
1
2
3
4
5
6
pd.pivot_table(data=df,index='Year',values='Global_Sales',aggfunc=np.mean,margins=True,margins_name='总计数')
Global_Sales
Year
1980 1.26
1981 077
...
指定columns
1
pd.pivot_table(data=df,index='Year',columns='Genre',values='Global_Sales',aggfunc=np.mean,margins=True,margins_name='总计数')
1
2
3
4
5
6
7
Y
Genre Action Adventure Fighting ...
Year
1980 0.34 NaN 0.77
1961 0.69 NaN NaN
1983 0.40 0.40 NaN
...
fill_value
1
2
3
4
# 使用空缺值填充
pd.pivot_table(data=df,index='Year',columns='Genre',values='Global_Sales',aggfunc=np.mean,margins=True,margins_name='总计数',fill_value=-1)

这里不写value的话,会生成列层次索引(所有数值类型都会统计)
多个aggfunc
1
pd.pivot_table(data=df,index='Year',columns='Genre',values='Global_Sales',aggfunc=[np.mean,np.sum,np.median],margins=True,margins_name='总计数',fill_value=-1)
1
index,columns,aggunc,values等可以是多个

交叉表

1
更多用于计算分组频率(或者样本个数)
1
2
3
4
5
6
7
8
pd.crosstab(index=df['Platform'],columns=df['Genre'],margins=True)

Genre action adventure fighting ...
platfrom
2600 61 2 2
3DO 0 1 0
3DS 182 37 14
...
,normalize
1
2
3
all:就上面的,每个位置数据除以总数  
index:每一行每个数据除以当前行总数
column:每一列每个数据除以当前列总数
1
pd.crosstab(index=df['Platform'],columns=df['Genre'],margins=True,normalize='all')

其它函数

1
df的某一列数据格式为:2024年6月 识别成字符串

时间函数

pd.to_datetime(xx)
1
2
3
4
5
6
df['c1']=pd.to_datetime(df['c1'],format='%Y年%m月',errors='coerce')
errors参数用于对假如这一列有异常值时进行处理,这里是用空值处理


一个新的数据类型:datetime64
timedelta64时间戳格式
1
pd.to_datetime(字符串时间列)
pd.datetime.today()
1
2
3
4
5
6
7
8
9
10
11
pd.datetime.today()
计算时间差:sec_cars['diff_day']=pd.datetime.today()-df['时间列']
上面的sec_cars['diff_day']为时间戳timedelta64

sec_cars['diff_day']/np.timedelta64(1,'D') #计算相差多少天
sec_cars['diff_day']/np.timedelta64(7,'D') #计算相差多少天
sec_cars['diff_day']/np.timedelta64(30,'D') #计算相差多少月

(sec_cars['diff_day']/np.timedelta64(1,'D') ).astype('int')

df[‘时间列’].dt.year 取年份
df.dt.date和df.dt.time
1
2
3
4
5
df['date']=df['InvoiceDate'].dt.date # InvoiceDate列datetime列,这里只取日期
2025-06-28

df['InvoiceDate'].dt.time # InvoiceDate列datetime列,这里只取时间
12:30:50

字符串函数

series对象.str[xx:xx]
1
2
3
4
5
6
7
例如数据为:
8.9万
3.7万
...
需要去掉万

df[列]=df['列'].str[:-1].astype('float')
series对象.str.replace(xx,xx)
1
2
3
4
5
6
7
8
9
10
11
12
视频中遇得到了一种缺失值情况,就是缺失值是特定字符(暂无),而不是空 ,可以在read_csv方法读取数据时,传参数处理
当是上面用这种情况时,查看是否有缺失值,可以用series对象.unique()或者.value_count()方法查看分析

series对象.unique()方法

c1
国4,-
国5

国1
...
series对象.str.replace('-','')

特定缺失值判断

1
2
视频中遇得到了一种缺失值情况,就是缺失值是特定字符(暂无),而不是空 ,可以在read_csv方法读取数据时,传参数处理
当是上面用这种情况时,查看是否有缺失值,可以用series对象.unique()或者.value_count()方法查看分析

apply(xx)

手机号中间隐藏
1
2
手机号中间部分隐藏
df['tel']=df['tel'].apply(lambda x:x.replace(x[3:7],'****'))
获取邮箱域名
1
df['email'] = df['email'].apply(lambda x:x.split('@')[1])
1
mysql中这个很简单,用substring_index(str,'@',-1)
sample抽样
1
2
3
4
data=df.sample(n=50000,replace=False) 
# replace 是否是放回抽样

2025-06-28 12:30:50
df.dt.date和df.dt.time
1
2
3
4
5
df['date']=df['InvoiceDate'].dt.date # InvoiceDate列datetime列,这里只取日期
2025-06-28

df['InvoiceDate'].dt.time # InvoiceDate列datetime列,这里只取时间
12:30:50
dataframe两列相乘
1
2
3
4
5
data['total_price'] = data[['Quantity','UnitPrice']].apply(np.prod,axis=1) #两列相乘
grouped_data=data.groupby(by='date').sum() #sum对数值型数据进行统计,这里会对所有数值型列进行统计

grouped_data的行标签变成了字符串,本来date是datetime类型,对行标签进行转换成日期数据类型
grouped_data.index = pd.to_datetime(grouped_data.index)
1
2
3
也可以直接两个series对象相乘

mysql就很简单了,直接select c1*c2

series.pct_change

1
2
3
group_data['总价变化率']=grouped_data['total_price'].pct_change()

#本质是使用了shift
1
mysql可以用lag()over()实现

series.rolling(n)

1
2
grouped_data['SMA_5'] = grouped_data['total_price'].rolling(5).mean() #五个一组,每次移动一个单位
grouped_data[['SMA_5','SMA_10']].plot()

series.shift(xx)

1
2
3
4
grouped_data['total_price'].shift(1) #正数向下平移一个单位
grouped_data['total_price'].shift(-1) #负数向上平移一个单位

索引不动,数据向上或者向下移动,无数据NAN