本文将介绍一些处理大型数据集的Pandas技巧,适用于数据分析和处理。
Pandas中apply函数应用方便,计算速度只比loop循环稍快。因此,在适当的 数据处理任务中,推荐使用Pandas内置函数ufuncs。Ufuncs是基于Numpy库, 以C语言实现的一类特殊函数,运行高效。
本文将重点介绍以下ufuncs的命令:.diff,.shift,.cumsum, .str commands(以字符串为操作对象),.dt commands(以日期为操作对象)等等。
示例数据包含不同人在暑期进行的活动,时间点和费用信息,数据如下:
import pandas as pd
# 借助原始数据构建DataFrame
df = pd.DataFrame(index = [1,6,0,3,2,4,5,7,8,9,10,11,12],
columns = ['name','activity','timestamp','money_spent'])
df['name'] = ['Chandler Bing','Harry Kane','John Doe','Joey Tribbiani','Monica Keller','Ross Geller','Harry Kane','John Doe','Joey Tribbiani','Monica Keller','Harry Kane','John Doe','John Doe']
df['activity'] = ['party','football','beach','party','travel','surfing','beach','party','travel','surfing','surfing','party','party']
df['timestamp'] = ['2017-08-04 13:30:00','2017-08-04 13:00:00','2017-08-04 10:00:00','2017-08-04 10:00:00','2017-08-04 07:00:00','2017-08-04 14:10:00','2017-08-04 14:00:00','2017-08-04 14:00:00','2017-08-04 07:00:00','2017-08-04 14:00:00','2017-08-04 07:00:00','2017-08-04 14:10:00','2017-08-04 15:10:00']
df['money_spent'] = [34,98,43,543,35,53,5,75,750,13,788,56,890]
df
在所有的字符串操作命令中,我们强烈推荐使用Pandas的字符串命令(Ufuncs函数)。
例如,你可以将某人的全名分解为两行,使用.str.split命令,设定expand = True。
df[['first name', 'last name']] = df.name.str.split(' ', expand= True) # 将全名分解为两列
df
Groupby是非常有用的Pandas命令,你可以依照某个列进行分组,并对另一列进行计数。 现在,本文利用groupby和value_counts计算每个人参加的活动数量。
df.groupby('name')['activity'].value_counts()
这叫做多层索引,允许在dataframe中存在不同层次的索引。 在此例中,'name'是主索引,'activity'是第二层次索引。
另一种获取该信息的方法是利用unstack命令,Unstack 将行转换为列,数据将会填充该表格。 若无数据,使用fillna命令以'0'填充缺失数据。
df.groupby('activity')['name'].value_counts().unstack().fillna(0)
以上我们已经获知每人参加的活动次数,接下来我们看看谁玩的时间最长?
最直接的方式是计算每个人不同时间点之间差值,利用groupby和diff函数。
import datetime
df['timestamp'] = df['timestamp'].map(lambda x: pd.to_datetime(x)) # 将字符型转化为日期时间型
df = df.sort_values(by=['name', 'timestamp'])
df['time_diff'] = df.groupby('name')['timestamp'].diff().fillna(0)
df[['name', 'timestamp', 'time_diff']]
若数据集足够大,采用另一种方式可以运行得更快,省略groupby,直接使用diff命令。 对不同人之间的时间差值做归零处理。
df = df.sort_values(by=['name', 'timestamp']) #进行排序
df['time_diff'] = df['timestamp'].diff() #计算时间差值
df.loc[df.name != df.name.shift(), 'time_diff'] = 0 #不同人之间的时间差值记为0
df
将时间差值单位转为为'秒':
df['time_diff'] = df.time_diff.dt.total_seconds()
df
获取每个活动的持续时间
df['activity_duration'] = df.time_diff.shift(-1).fillna(0)
df[['name', 'timestamp', 'activity', 'activity_duration', 'time_diff']]
累计数帮助获取每个人的活动次序。 例如,了解每个人第二个或者第三个活动项目:
df = df.sort_values(by=['name', 'timestamp']) #数据排序
df2 = df[df.groupby('name').cumcount()==1] #获取每个人的第二个活动
df2[['name', 'timestamp', 'activity']]
df3 = df[df.groupby('name').cumcount()==2] #获取每个人的第三个活动
df3[['name', 'timestamp', 'activity']]
累计和是数据的累积和。例如,你可以得到不同时间点每个人总花费。
df = df.sort_values(by = ['name', 'timestamp'])
df['money_spent_so_far'] = df.groupby('name')['money_spent'].cumsum()
df[['name', 'timestamp', 'activity', 'money_spent', 'money_spent_so_far']]
现在我们想知道每个人在不同活动上花费的时间。但有时候数据可能对同一个人参同一个活动连续记录两次。 我们使用新的命令排除这种情况的发生。
# 5. groupby, max, min for measuring the duration of activities
df = df.sort_values(by = ['name', 'activity'])
df['activity_change'] = (df.activity != df.activity.shift()) | (df.name != df.name.shift()) # 当人或者活动改变时,change=True
df['activity_num'] = df.groupby('name')['activity_change'].cumsum() # 计算活动个数
activity_duration = df.groupby(['name', 'activity_num', 'activity'])['activity_duration'].sum() # 计算总的活动时间
df
activity_duration
利用min,max,median等函数分析每个人持续时间最长的活动
activity_duration.reset_index().groupby('name').max() #取持续时间最大的活动