“分组”是数据整理经常进行的操作,它才是数据整理的起点。我们经常在处理大量数据的时候,想按照某种联系或某种特殊的关系来关联表中的一部分数据,进行统计分析,那么分组无疑是最高效的处理手段。
根据一些共有的值对行分组,groupby是pandas中最强大的功能之一。
import pandas as pd
# 载入准备好的泰坦尼克号数据集
dataframe = pd.read_csv('train.csv')
# 根据Sex列的值来进行分组,并计算每一组的平均值
print(dataframe.groupby('Sex').mean())
# 根据Survived列的值进行分组,进而通过Name来计算每组的个数
print(dataframe.groupby('Survived')['Name'].count())
# 根据Sex与Survived列的值进行分组,进而通过Age来计算每组的平均值
print(dataframe.groupby(['Sex', 'Survived'])['Age'].mean())
Sex PassengerId Survived Pclass Age
female 431.028662 0.742038 2.159236 27.915709
male 454.147314 0.188908 2.389948 30.726645
Survived
0 549
1 342
Name: Name, dtype: int64
Sex Survived
female 0 25.046875
1 28.847716
male 0 31.618056
1 27.276022
Name: Age, dtype: float64
【小提示】:初学者可能会写出下面这之一类代码:dataframe.groupby('Sex'),但是输出结果可能根本看不懂是什么意思。原因:groupby需要和一些作用与组(group)的操作配合使用(例如:平均值、中位数、总和等等)。
# 奇怪的输出结果
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000019FD8DE7F28>
resample():按时间段对行分组。
import pandas as pd
import numpy as np
# 创建日期范围,date_range()时间序列:起始日期06/06/2017,间隔30S,生成100000个
time_index = pd.date_range('06/06/2017', periods=100000, freq='30S')
# 创建数据帧,且index为日期
dataframe = pd.DataFrame(index=time_index)
# 创建一列随机变量:1~9共10个数,随机生成100000个
dataframe['Sale_Amount'] = np.random.randint(1, 10, 100000)
# 查看前4行
print(dataframe.head(4))
# 按周W进行分组,计算每一周的总和
print(dataframe.resample('W').sum())
# 按两周2W进行分组,计算每两周的平均值
print(dataframe.resample('2W').mean())
# 按每月M进行分组,计算每月的行数
print(dataframe.resample('M').count())
Sale_Amount
2017-06-06 00:00:00 3
2017-06-06 00:00:30 7
2017-06-06 00:01:00 7
2017-06-06 00:01:30 4
Sale_Amount
2017-06-11 86264
2017-06-18 101552
2017-06-25 101267
2017-07-02 100818
2017-07-09 100173
2017-07-16 10300
Sale_Amount
2017-06-11 5.000868
2017-06-25 4.989931
2017-07-09 4.996255
2017-07-23 5.038942
Sale_Amount
2017-06-30 72000
2017-07-31 28000
将pandas的列视为与Python中的其他序列一样:
import pandas as pd
# 载入准备好的泰坦尼克号数据集
dataframe = pd.read_csv('train.csv')
# 方法一:for循环,打印前两行中的名字的大写
for name in dataframe['Name'][0:2]:
print(name.upper())
# 方法二:列表解析
print([name.upper() for name in dataframe['Name'][0:2]])
BRAUND, MR. OWEN HARRIS
CUMINGS, MRS. JOHN BRADLEY
['BRAUND, MR. OWEN HARRIS', 'CUMINGS, MRS. JOHN BRADLEY']
【说明】:遍历一个列中的所有元素,并作某个操作有3个常见的方法:(1)for循环(2)列表解析(3)pandas的apply方法
apply对一列的所有元素应用一个内置的或者自定义的函数:
import pandas as pd
# 载入准备好的泰坦尼克号数据集
dataframe = pd.read_csv('train.csv')
# 方法三:创建一个函数:大写
def uppercase(x):
return x.upper()
# 应用函数,查看前两行
print(dataframe['Name'].apply(uppercase)[0:2])
0 BRAUND, MR. OWEN HARRIS
1 CUMINGS, MRS. JOHN BRADLEY
Name: Name, dtype: object
groupby与apply联合使用:
import pandas as pd
dataframe = pd.read_csv('train.csv')
print(dataframe.groupby('Sex').count())
# 对行分组,然后在每一组上应用函数
print(dataframe.groupby('Sex').apply(lambda x: x.count()*100))
Sex PassengerId Survived Pclass Name Age
female 314 314 314 314 261
male 577 577 577 577 453
Sex PassengerId Survived Pclass Name Sex Age
female 31400 31400 31400 31400 31400 26100
male 57700 57700 57700 57700 57700 45300
concat方法:参数axis=0,延着行方向连接数据。
import pandas as pd
# 注意:columns=['id', 'first', 'last']是为了保证数据帧打印出来的顺序
# 创建数据帧
data_a = {'id': ['1', '2', '3'],
'first': ['Alex', 'Amy', 'Allen'],
'last': ['Anderson', 'Ackerman', 'Ali']}
dataframe_a = pd.DataFrame(data_a, columns=['id', 'first', 'last'])
# 创建数据帧
data_b = {'id': ['4', '5', '6'],
'first': ['Bill', 'Brian', 'Bran'],
'last': ['Bonder', 'Black', 'Balwner']}
dataframe_b = pd.DataFrame(data_b, columns=['id', 'first', 'last'])
# 沿着行和列连接两个数据帧
print(pd.concat([dataframe_a, dataframe_b], axis=0))
print(pd.concat([dataframe_a, dataframe_b], axis=1))
id first last
0 1 Alex Anderson
1 2 Amy Ackerman
2 3 Allen Ali
0 4 Bill Bonder
1 5 Brian Black
2 6 Bran Balwner
id first last id first last
0 1 Alex Anderson 4 Bill Bonder
1 2 Amy Ackerman 5 Brian Black
2 3 Allen Ali 6 Bran Balwner
可能说到连接,你还会想到另一种常见的方法,在之前的一篇文章中已经用过1次:
# 创建新的一行
row_new = pd.Series([10, 'Chris', 'Chillon'], index=['id', 'first', 'last'])
# append():增加一行
print(dataframe_a.append(row_new, ignore_index=True))
id first last
0 1 Alex Anderson
1 2 Amy Ackerman
2 3 Allen Ali
3 10 Chris Chillon
merger(): 巧用on参数来设置合并的类型
import pandas as pd
# 创建数据帧
employee_data = {'id': ['1', '2', '3', '4'],
'name': ['Amy', 'Allen', 'Alice', 'Tim']}
dataframe_employees = pd.DataFrame(employee_data, columns=['id', 'name'])
# 创建数据帧
sales_data = {'id': ['3', '4', '5', '6'],
'total_sales': [23456, 2512, 2345, 1455]}
dataframe_sales = pd.DataFrame(sales_data, columns=['id', 'total_sales'])
print(dataframe_employees)
print(dataframe_sales)
id name
0 1 Amy
1 2 Allen
2 3 Alice
3 4 Tim
id total_sales
0 3 23456
1 4 2512
2 5 2345
3 6 1455
# 合并数据帧,默认等值连接
print(pd.merge(dataframe_employees, dataframe_sales, on='id'))
# how='outer'是外连接(outer join)
print(pd.merge(dataframe_employees, dataframe_sales, on='id', how='outer'))
# how='left'是左连接
print(pd.merge(dataframe_employees, dataframe_sales, on='id', how='left'))
# 根据id合并共有的部分
print(pd.merge(dataframe_employees, dataframe_sales, left_on='id', right_on='id'))
id name total_sales
0 3 Alice 23456
1 4 Tim 2512
id name total_sales
0 1 Amy NaN
1 2 Allen NaN
2 3 Alice 23456.0
3 4 Tim 2512.0
4 5 NaN 2345.0
5 6 NaN 1455.0
id name total_sales
0 1 Amy NaN
1 2 Allen NaN
2 3 Alice 23456.0
3 4 Tim 2512.0
id name total_sales
0 3 Alice 23456
1 4 Tim 2512
【小提示】:其实上述几个合并过程类似于,数据库SQL的查询语句
评论