python 数据分析--数据处理工具Pandas(2)

2023-10-30

前面的学习中主要了解了Pandas如何构造序列和数据框,如何读取和写入各种格式的数据,以及如何对数据进行初步描述,本文将进一步了解Pandas如何处理字符串和日期数据,数据清洗,获取数据子集,透视表,分组聚合操作等内容。

4. Pandas处理字符串和日期数据

待处理的数据表[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIBfCT7G-1585923940264)(attachment:image.png)]

数据处理要求:

  • 更改出生日期birthday和手机号tel两个字段的数据类型。
  • 根据出生日期birthday和开始工作日期start_work两个字段新增年龄和工龄两个字段。
  • 将手机号tel的中间四位隐藏起来。
  • 根据邮箱信息新增邮箱域名字段。
  • 基于other字段取出每个人员的专业信息。
import pandas as pd

#读入数据
employee_info = pd.read_excel(r"E:/Data/3/data_test03.xlsx",header=0)
employee_info.dtypes
name                  object
gender                object
birthday              object
start_work    datetime64[ns]
income                 int64
tel                    int64
email                 object
other                 object
dtype: object
# 更改数据类型
employee_info.birthday = pd.to_datetime(employee_info.birthday, format="%Y/%m/%d")
employee_info.tel = employee_info.tel.astype('str')
employee_info.dtypes
name                  object
gender                object
birthday      datetime64[ns]
start_work    datetime64[ns]
income                 int64
tel                   object
email                 object
other                 object
dtype: object
# 新增年龄和工龄字段
# 年龄 = 当天日期的年份 - 生日那一天的年份
# 工龄 = 当天日期的年份 - 开始工作那一天的年份
employee_info['age'] = pd.datetime.today().year - employee_info.birthday.dt.year
employee_info['workage'] = pd.datetime.today().year - employee_info.start_work.dt.year

# 新增邮箱域名字段
# 字符串分割、巧用了匿名函数 lambda
# split分出来的数据有两部分[邮箱名,域名],域名的索引为1

employee_info['email_domain'] = employee_info.email.apply(func = lambda x: x.split('@')[1])  
employee_info
name gender birthday start_work income tel email other age workage email_domain
0 赵一 1989-08-10 2012-09-08 15000 13611011234 zhaoyi@qq.com {教育:本科,专业:电子商务,爱好:运动} 31 8 qq.com
1 王二 1990-10-02 2014-03-06 12500 13500012234 wanger@163.com {教育:大专,专业:汽修,爱好:} 30 6 163.com
2 张三 1987-03-12 2009-01-08 18500 13515273330 zhangsan@qq.com {教育:本科,专业:数学,爱好:打篮球} 33 11 qq.com
3 李四 1991-08-16 2014-06-04 13000 13923673388 lisi@gmail.com {教育:硕士,专业:统计学,爱好:唱歌} 29 6 gmail.com
4 刘五 1992-05-24 2014-08-10 8500 17823117890 liuwu@qq.com {教育:本科,专业:美术,爱好:} 28 6 qq.com
5 雷六 1986-12-10 2010-03-10 15000 13712345612 leiliu@126.com {教育:本科,专业:化学,爱好:钓鱼} 34 10 126.com
6 贾七 1993-04-10 2015-08-01 9000 13178734511 jiaqi@136.com {教育:硕士,专业:物理,爱好:健身} 27 5 136.com
7 吴八 1988-07-19 2014-10-12 13500 17822335317 wuba@qq.com {教育:本科,专业:政治学,爱好:读书} 32 6 qq.com
# 隐藏电话号码中间四位数
# 字符串替换,巧用了匿名函数lambda
employee_info.tel = employee_info.tel.apply(func = lambda x: x.replace(x[3:7],'****'))
employee_info
name gender birthday start_work income tel email other age workage email_domain
0 赵一 1989-08-10 2012-09-08 15000 136****1234 zhaoyi@qq.com {教育:本科,专业:电子商务,爱好:运动} 31 8 qq.com
1 王二 1990-10-02 2014-03-06 12500 135****2234 wanger@163.com {教育:大专,专业:汽修,爱好:} 30 6 163.com
2 张三 1987-03-12 2009-01-08 18500 135****3330 zhangsan@qq.com {教育:本科,专业:数学,爱好:打篮球} 33 11 qq.com
3 李四 1991-08-16 2014-06-04 13000 139****3388 lisi@gmail.com {教育:硕士,专业:统计学,爱好:唱歌} 29 6 gmail.com
4 刘五 1992-05-24 2014-08-10 8500 178****7890 liuwu@qq.com {教育:本科,专业:美术,爱好:} 28 6 qq.com
5 雷六 1986-12-10 2010-03-10 15000 137****5612 leiliu@126.com {教育:本科,专业:化学,爱好:钓鱼} 34 10 126.com
6 贾七 1993-04-10 2015-08-01 9000 131****4511 jiaqi@136.com {教育:硕士,专业:物理,爱好:健身} 27 5 136.com
7 吴八 1988-07-19 2014-10-12 13500 178****5317 wuba@qq.com {教育:本科,专业:政治学,爱好:读书} 32 6 qq.com
# 根据other 字段提取每个人的专业信息
# 用正则表达式匹配专业字段,主要在匹配时 : 和 , 均为中文输入法,英文无法匹配的
employee_info['profession'] = employee_info.other.str.findall('专业:(.*?),')

# findall 提取出来的数据带[] 去除[]
employee_info.profession = employee_info.profession.astype('str')
employee_info.profession = employee_info.profession.apply(func = lambda x: x.replace(x[:],x[1:-1]))
employee_info.profession = employee_info.profession.apply(func = lambda x: x.replace(x[0],' '))
employee_info.head()
name gender birthday start_work income tel email other age workage email_domain profession
0 赵一 1989-08-10 2012-09-08 15000 136****1234 zhaoyi@qq.com {教育:本科,专业:电子商务,爱好:运动} 31 8 qq.com 电子商务
1 王二 1990-10-02 2014-03-06 12500 135****2234 wanger@163.com {教育:大专,专业:汽修,爱好:} 30 6 163.com 汽修
2 张三 1987-03-12 2009-01-08 18500 135****3330 zhangsan@qq.com {教育:本科,专业:数学,爱好:打篮球} 33 11 qq.com 数学
3 李四 1991-08-16 2014-06-04 13000 139****3388 lisi@gmail.com {教育:硕士,专业:统计学,爱好:唱歌} 29 6 gmail.com 统计学
4 刘五 1992-05-24 2014-08-10 8500 178****7890 liuwu@qq.com {教育:本科,专业:美术,爱好:} 28 6 qq.com 美术
# 剔除birthday,start_work和other变量
# 需要将axis参数设置为1,因为默认drop方法是用来删除数据框中的行记录。
employee_info.drop(['birthday','start_work','other'], axis=1,inplace=True)
employee_info
name gender income tel email age workage email_domain profession
0 赵一 15000 136****1234 zhaoyi@qq.com 31 8 qq.com 电子商务
1 王二 12500 135****2234 wanger@163.com 30 6 163.com 汽修
2 张三 18500 135****3330 zhangsan@qq.com 33 11 qq.com 数学
3 李四 13000 139****3388 lisi@gmail.com 29 6 gmail.com 统计学
4 刘五 8500 178****7890 liuwu@qq.com 28 6 qq.com 美术
5 雷六 15000 137****5612 leiliu@126.com 34 10 126.com 化学
6 贾七 9000 131****4511 jiaqi@136.com 27 5 136.com 物理
7 吴八 13500 178****5317 wuba@qq.com 32 6 qq.com 政治学

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-viK3mTil-1585923940265)(attachment:image.png)]

5. Pandas 数据清洗

在数据处理过程中,一般都需要进行数据的清洗工作,数据清洗过程主要负责看数据集是否存在重复、是否存在缺失、数据是否具有完整性和一致性、数据中是否存在异常值等。这些问题都不利于数据分析,需要加以处理。

5.1 重复观测处理

在搜集数据过程中,可能会存在重复观测的出现,例如通过网络爬虫,就比较容易产生重复数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-woWeaqTU-1585923940266)(attachment:image.png)]
上面的数据就是通过爬虫获得某APP市场中电商类APP的下载量数据(部分),通过肉眼,是能够发现这10行数据中的重复项的,例如,唯品会出现了两次、当当出现了三次。如果搜集上来的数据不是10行,而是10万行,甚至更多时,就无法通过肉眼的方式检测数据是否存在重复项了。

import pandas as pd 

dsapp = pd.read_excel(r"E:/Data/3/data_test04.xlsx")

# 重复观测检测
#使用duplicated方法进行验证,但是该方法返回的是数据集每一行的检验结果,即10行数据会返回10个bool值。
# 加any进行判断,只要有一个检测到,就代表有

print("是否存在重复观测:\n",any(dsapp.duplicated()))
是否存在重复观测:
 True
#删除重复数据

dsapp.drop_duplicates(inplace=True)
dsapp
appcategory appname comments install love size update
0 网上购物-商城-团购-优惠-快递 每日优鲜 1297 204.7万 89.00% 15.16MB 2017年10月11日
1 网上购物-商城 苏宁易购 577 7996.8万 73.00% 58.9MB 2017年09月21日
2 网上购物-商城-优惠 唯品会 2543 7090.1万 86.00% 41.43MB 2017年10月13日
4 网上购物-商城 拼多多 1921 3841.9万 95.00% 13.35MB 2017年10月11日
5 网上购物-商城-优惠 寺库奢侈品 1964 175.4万 100.00% 17.21MB 2017年09月30日
6 网上购物-商城 淘宝 14244 4.6亿 68.00% 73.78MB 2017年10月13日
7 网上购物-商城-团购-优惠 当当 134 1615.3万 61.00% 37.01MB 2017年10月17日

5.2 缺失值处理

缺失值是指数据集中的某些观测存在遗漏的指标值,缺失值的存在同样会影响到数据分析和挖掘的结果。导致观测的缺失可能有两方面原因,一方面是人为原因(如记录过程中的遗漏、个人隐私而不愿透露等),另一方面是机器或设备的故障所导致(如断电或设备老化等原因)。一般而言,当遇到缺失值(Python中用NaN表示)时,可以采用三种方法处置,分别是删除法、替换法和插补法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MysIVi7X-1585923940266)(attachment:image.png)]
上面的数据来自于某游戏公司的用户注册信息(仅以10行记录为例,该数据集中存在4条红色标注的缺失观测。

import pandas as pd 

Game_user = pd.read_excel(r"E:\Data\3\data_test05.xlsx")
print("数据集是否存在缺失值:\n",any(Game_user.isnull()))

数据集是否存在缺失值:
 True

5.2.1 删除法

# 1. 删除法处理
# 在副本上删除所有缺失的行,Game_user 不变
Game_user.dropna()    
uid regit_date gender age income
0 81200457 2016-10-30 M 23.0 6500.0
1 81201135 2016-11-08 M 27.0 10300.0
3 84639281 2017-04-17 M 26.0 6000.0
6 63881943 2015-10-07 M 21.0 10000.0
8 77638351 2016-07-12 M 25.0 18000.0
# 删除缺失值最多的那一列变量
Game_user.drop('age',axis=1) 
uid regit_date gender income
0 81200457 2016-10-30 M 6500.0
1 81201135 2016-11-08 M 10300.0
2 80043782 2016-10-13 F 13500.0
3 84639281 2017-04-17 M 6000.0
4 73499801 2016-03-21 NaN 4500.0
5 72399510 2016-01-18 M NaN
6 63881943 2015-10-07 M 10000.0
7 35442690 2015-04-10 F 5800.0
8 77638351 2016-07-12 M 18000.0
9 85200189 2017-05-18 M NaN

5.2.2 替换法

# 2. 替换法
# 缺失值用前一行值填充
Game_user.fillna(method='ffill')
uid regit_date gender age income
0 81200457 2016-10-30 M 23.0 6500.0
1 81201135 2016-11-08 M 27.0 10300.0
2 80043782 2016-10-13 F 27.0 13500.0
3 84639281 2017-04-17 M 26.0 6000.0
4 73499801 2016-03-21 M 26.0 4500.0
5 72399510 2016-01-18 M 19.0 4500.0
6 63881943 2015-10-07 M 21.0 10000.0
7 35442690 2015-04-10 F 21.0 5800.0
8 77638351 2016-07-12 M 25.0 18000.0
9 85200189 2017-05-18 M 22.0 18000.0
# 缺失值用后一行填充
Game_user.fillna(method='bfill')
uid regit_date gender age income
0 81200457 2016-10-30 M 23.0 6500.0
1 81201135 2016-11-08 M 27.0 10300.0
2 80043782 2016-10-13 F 26.0 13500.0
3 84639281 2017-04-17 M 26.0 6000.0
4 73499801 2016-03-21 M 19.0 4500.0
5 72399510 2016-01-18 M 19.0 10000.0
6 63881943 2015-10-07 M 21.0 10000.0
7 35442690 2015-04-10 F 25.0 5800.0
8 77638351 2016-07-12 M 25.0 18000.0
9 85200189 2017-05-18 M 22.0 NaN

method参数可以接受’ffill’和’bfill’两种值,分别代表前向填充和后向填充。前向填充是指用缺失值的前一个值替换(如左表所示),而后向填充则表示用缺失值的后一个值替换(如右表所示)。右表中的最后一个记录仍包含缺失值,是因为后向填充法找不到该缺失值的后一个值用于替换。缺失值的前向填充或后向填充一般适用于时间序列型的数据集,因为这样的数据前后具有连贯性,而一般的独立性样本并不适用该方法。

# 常数替换
Game_user.fillna(value = 0)
uid regit_date gender age income
0 81200457 2016-10-30 M 23.0 6500.0
1 81201135 2016-11-08 M 27.0 10300.0
2 80043782 2016-10-13 F 0.0 13500.0
3 84639281 2017-04-17 M 26.0 6000.0
4 73499801 2016-03-21 0 0.0 4500.0
5 72399510 2016-01-18 M 19.0 0.0
6 63881943 2015-10-07 M 21.0 10000.0
7 35442690 2015-04-10 F 0.0 5800.0
8 77638351 2016-07-12 M 25.0 18000.0
9 85200189 2017-05-18 M 22.0 0.0
# 统计值替换
Game_user.fillna(value= {'gender':Game_user.gender.mode()[0],
                         'age':Game_user.age.median(),
                        'income':Game_user.income.mean()})
uid regit_date gender age income
0 81200457 2016-10-30 M 23.0 6500.0
1 81201135 2016-11-08 M 27.0 10300.0
2 80043782 2016-10-13 F 23.0 13500.0
3 84639281 2017-04-17 M 26.0 6000.0
4 73499801 2016-03-21 M 23.0 4500.0
5 72399510 2016-01-18 M 19.0 9325.0
6 63881943 2015-10-07 M 21.0 10000.0
7 35442690 2015-04-10 F 23.0 5800.0
8 77638351 2016-07-12 M 25.0 18000.0
9 85200189 2017-05-18 M 22.0 9325.0

如上代码并没有实际改变df数据框的结果,因为dropna、drop和fillna方法并没有使inplace参数设置为True。可以在实际的学习和工作中挑选一个适当的缺失值处理方法,然后将该方法中的inplace参数设置为True,进而可以真正地改变你所处理的数据集。

5.3 异常值处理

异常值是指那些远离正常值的观测,即“不合群”观测。导致异常值的出现一般是人为的记录错误或者是设备的故障等,异常值的出现会对模型的创建和预测产生严重的后果。当然异常值也不一定都是坏事,有些情况下,通过寻找异常值就能够给业务带来良好的发展,如销毁“钓鱼”网站、关闭“薅羊毛”用户的权限等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cg7IWD46-1585923940268)(attachment:image.png)]

这两种方法的选择标准如下,如果数据近似服从正态分布时,优先选择n个标准差法,因为数据的分布相对比较对称;否则优先选择箱线图法,因为分位数并不会受到极端值的影响。当数据存在异常时,一般可以使用删除法将异常值删除(前提是异常观测的比例不能太大)、替换法(可以考虑使用低于判别上限的最大值或高于判别下限的最小值替换、使用均值或中位数替换等)。下面将以年为单位的太阳黑子个数为例(时间范围:1700—1988),识别并处理异常值:

# 1. 看两种方法是否都存在异常值

import pandas as pd

#数据读入
sunspots = pd.read_table(r"E:\Data\3\sunspots.csv", sep = ',')

# 标准差法检测异常值
xmean = sunspots.counts.mean()
xstd = sunspots.counts.std()
print("标准差法异常上限检测:\n",any(sunspots > xmean + 2 * xstd))
print("标准差法异常下限检测:\n",any(sunspots < xmean - 2 * xstd))

# 箱线法检测异常值
Q1 = sunspots.counts.quantile(q = 0.25)
Q3 = sunspots.counts.quantile(q = 0.75)
IQR = Q3 - Q1
print("箱线法异常上限检测:\n",any(sunspots  > Q3 + 1.5 * IQR ))
print("箱线法异常下限检测:\n",any(sunspots < Q1 - 1.5 * IQR ))
标准差法异常上限检测:
 True
标准差法异常下限检测:
 True
箱线法异常上限检测:
 True
箱线法异常下限检测:
 True

不管是标准差检验法还是箱线图检验法,都发现太阳黑子数据中存在异常值,而且异常值都是超过上限临界值的。接下来,通过绘制太阳黑子数量的直方图和核密度曲线图,用于检验数据是否近似服从正态分布,进而选择一个最终的异常值判别方法:

# 2. 绘制直方图和核密度曲线图,确定采用何种异常判别法。
import matplotlib.pyplot as plt

plt.style.use('ggplot')
sunspots.counts.plot(kind = 'hist', bins =30, normed = True)
sunspots.counts.plot(kind = 'kde')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9VooviMK-1585923940268)(output_37_0.png)]
很明显,不管是直方图还是核密度曲线,都不服从正太分布,所以采用箱线法进行异常检测,此处也选用替换法来处理异常值。

# 替换法处理异常值:
print("异常值替换前的数据统计特征:\n", sunspots.counts.describe())
print("\n")

#箱线图中的异常值判别上限
UL = Q3 + 1.5 * IQR
print("判别异常值的上限临界值:\n", UL)

# 从数据中找出低于判别上限的最大值
replace_value = sunspots.counts[sunspots.counts < UL].max()
sunspots.counts[sunspots.counts > UL] = replace_value
print("\n")
print("异常值替换后的数据统计特征:\n", sunspots.counts.describe())
异常值替换前的数据统计特征:
 count    289.000000
mean      48.613495
std       39.474103
min        0.000000
25%       15.600000
50%       39.000000
75%       68.900000
max      190.200000
Name: counts, dtype: float64


判别异常值的上限临界值:
 148.85000000000002


异常值替换后的数据统计特征:
 count    289.000000
mean      48.066090
std       37.918895
min        0.000000
25%       15.600000
50%       39.000000
75%       68.900000
max      141.700000
Name: counts, dtype: float64


D:\Anaconda\lib\site-packages\ipykernel_launcher.py:11: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  # This is added back by InteractiveShellApp.init_path()

6. 获取数据子集

有时数据读入后并不是对整体数据进行分析,而是数据中的部分子集,例如,对于地铁乘客量可能只关心某些时间段的流量、对于商品的交易可能只需要分析某些颜色的价格变动、对于医疗诊断数据可能只对某个年龄段的人群感兴趣等。

在Pandas模块中实现数据框子集的获取可以使用iloc、loc和ix三种“方法”,这三种方法既可以对数据行进行筛选,也可以实现变量的挑选它们的语法可以表示成[rows_select,cols_select]。

df1 = pd.DataFrame({'name':['张三','李四','王二','丁一','李五'],
                    'gender':['男','女','女','女','男'],
                    'age':[23,26,22,25,27]},
                    columns = ['name','gender','age'])
df1
name gender age
0 张三 23
1 李四 26
2 王二 22
3 丁一 25
4 李五 27
# 取出所有女性的姓名和年龄
df1.iloc[1:4,[0,2]]
name age
1 李四 26
2 王二 22
3 丁一 25
df1.loc[1:3,['name','age']]
name age
1 李四 26
2 王二 22
3 丁一 25
df1.ix[1:3,[0,2]]
name age
1 李四 26
2 王二 22
3 丁一 25
# 假如数据没有行号
df2 = df1.set_index('name')
df2

df2.iloc[1:4,:]
df2.loc[['李四','王二','丁一'],:]

gender age
name
李四 26
王二 22
丁一 25
# df2.ix[1:4,:]

在上面的df1数据集中,如何返回所有男性的姓名和年龄,如果是基于条件的记录筛选,只能使用loc和ix两种方法。正如代码所示,对iloc方法的那行代码做注释,是因为iloc不允许使用条件筛选。

# 使用筛选条件,取出所有男性的姓名和年龄
# df1.iloc[df1.gender == '男',]
df1.loc[df1.gender == '男',['name','age']]
df1.ix[df1.gender == '男',['name','age']]
name age
0 张三 23
4 李五 27

7. 透视表、合并与连接、分组聚合

7.1 透视表

Pandas模块提供了实现透视表功能的pivot_table函数,*该功能的主要目的就是实现数据的汇总统计。例如,按照某个分组变量统计商品的平均价格、销售数量、最大利润等,或者按照某两个分组变量构成统计学中的列联表(计数统计),甚至是基于多个分组变量统计各组合下的均值、中位数、总和等。

  • data:指定需要构造透视表的数据集。
  • values:指定需要拉入“数值”框的字段列表。
  • index:指定需要拉入“行标签”框的字段列表。
  • columns:指定需要拉入“列标签”框的字段列表。
  • aggfunc:指定数值的统计函数,默认为统计均值,也可以指定numpy模块中的其他统计函数。
  • fill_value:指定一个标量,用于填充缺失值。
  • margins:bool类型参数,是否需要显示行或列的总计值,默认为False。
  • dropna:bool类型参数,是否需要删除整列为缺失的字段,默认为True。
  • margins_name:指定行或列的总计名称,默认为All。
# 数据读取
diamonds = pd.read_table(r"E:/Data/3/diamonds.csv", sep = ',')

# 单个分组变量的均值统计
pd.pivot_table(data= diamonds, index = 'color',values = 'price', 
               margins=True, margins_name='总计')
price
color
D 3169.954096
E 3076.752475
F 3724.886397
G 3999.135671
H 4486.669196
I 5091.874954
J 5323.818020
总计 3932.799722
import numpy as np
pd.pivot_table(data=diamonds, index='clarity', columns='cut', values = 'carat', 
               aggfunc= np.size, margins=True, margins_name='总计')
cut Fair Good Ideal Premium Very Good 总计
clarity
I1 210.0 96.0 146.0 205.0 84.0 741.0
IF 9.0 71.0 1212.0 230.0 268.0 1790.0
SI1 408.0 1560.0 4282.0 3575.0 3240.0 13065.0
SI2 466.0 1081.0 2598.0 2949.0 2100.0 9194.0
VS1 170.0 648.0 3589.0 1989.0 1775.0 8171.0
VS2 261.0 978.0 5071.0 3357.0 2591.0 12258.0
VVS1 17.0 186.0 2047.0 616.0 789.0 3655.0
VVS2 69.0 286.0 2606.0 870.0 1235.0 5066.0
总计 1610.0 4906.0 21551.0 13791.0 12082.0 53940.0

7.2 多表合并

Pandas模块同样提供了关于多表之间的合并操作concat函数:

  • objs:指定需要合并的对象,可以是序列、数据框或面板数据构成的列表。
  • axis:指定数据合并的轴,默认为0,表示合并多个数据的行,如果为1,就表示合并多个数据的列。
  • join:指定合并的方式,默认为outer,表示合并所有数据,如果改为inner,表示合并公共部分的数据。
  • join_axes:合并数据后,指定保留的数据轴。
  • ignore_index:bool类型的参数,表示是否忽略原数据集的索引,默认为False,如果设True,就表示忽略原索引并生成新索引。
  • keys:为合并后的数据添加新索引,用于区分各个数据部分。
df1 = pd.DataFrame({'name':['张三','李四','王二'],
                    'gender':['男','女','女'],
                    'age':[23,26,22,]} )
df2 = pd.DataFrame({'name':['丁一','李五'],
                    'gender':['女','男'],
                    'age':[25,27]} )
pd.concat([df1,df2],keys = ['df1','df2'], axis=0)
age gender name
df1 0 23 张三
1 26 李四
2 22 王二
df2 0 25 丁一
1 27 李五
df2 = pd.DataFrame({'Name':['丁一','李五'],
                    'gender':['女','男'],
                    'age':[25,27]} )
pd.concat([df1,df2],keys = ['df1','df2'])
Name age gender name
df1 0 NaN 23 张三
1 NaN 26 李四
2 NaN 22 王二
df2 0 丁一 25 NaN
1 李五 27 NaN

7.3 多表连接

Pandas模块同样提供了关于多表之间的连接操作merge函数,函数的最大缺点是,每次只能操作两张数据表的连接,如果有n张表需要连接,则必须经过n-1次的merge函数使用。

  • left:指定需要连接的主表。
  • right:指定需要连接的辅表。
  • how:指定连接方式,默认为inner内连,还有其他选项,如左连left、右连right和外连
  • outer。on:指定连接两张表的共同字段。
  • left_on:指定主表中需要连接的共同字段。
  • right_on:指定辅表中需要连接的共同字段。
  • left_index:bool类型参数,是否将主表中的行索引用作表连接的共同字段,默认为False。
  • right_index:bool类型参数,是否将辅表中的行索引用作表连接的共同字段,默认为False。
  • sort:bool类型参数,是否对连接后的数据按照共同字段排序,默认为False。
  • suffixes:如果数据连接的结果中存在重叠的变量名,则使用各自的前缀进行区分。
# 构造数据集
df3 = pd.DataFrame({'id':[1,2,3,4,5],'name':['张三','李四','王二','丁一','赵五'],'age':[27,24,25,23,25],'gender':['男','男','男','女','女']})
df4 = pd.DataFrame({'Id':[1,2,2,4,4,4,5],'kemu':['科目1','科目1','科目2','科目1','科目2','科目3','科目1'],'score':[83,81,87,75,86,74,88]})
df5 = pd.DataFrame({'id':[1,3,5],'name':['张三','王二','赵五'],'income':[13500,18000,15000]})

# 三表的数据连接
# 首先df3和df4连接
merge1 = pd.merge(left = df3, right = df4, how = 'left', left_on='id', right_on='Id')
merge1

# 再将连接结果与df5连接
merge2 = pd.merge(left = merge1, right = df5, how = 'left')
merge2
age gender id name Id kemu score income
0 27 1 张三 1.0 科目1 83.0 13500.0
1 24 2 李四 2.0 科目1 81.0 NaN
2 24 2 李四 2.0 科目2 87.0 NaN
3 25 3 王二 NaN NaN NaN 18000.0
4 23 4 丁一 4.0 科目1 75.0 NaN
5 23 4 丁一 4.0 科目2 86.0 NaN
6 23 4 丁一 4.0 科目3 74.0 NaN
7 25 5 赵五 5.0 科目1 88.0 15000.0

7.4 分组聚合

# 通过groupby方法,指定分组变量
grouped = diamonds.groupby(by = ['color','cut'])

# 对分组变量进行统计汇总
result = grouped.aggregate({'color':np.size, 'carat':np.min, 'price':np.mean})

# 调整变量名的顺序
result = pd.DataFrame(result, columns=['color','carat','price'])

# 数据集重命名
result.rename(columns={'color':'counts','carat':'min_weight','price':'avg_price'}, inplace=True)

# 将行索引变量数据框的变量
# result.reset_index(inplace=True)
result
counts min_weight avg_price
color cut
D Fair 163 0.25 4291.061350
Good 662 0.23 3405.382175
Ideal 2834 0.20 2629.094566
Premium 1603 0.20 3631.292576
Very Good 1513 0.23 3470.467284
E Fair 224 0.22 3682.312500
Good 933 0.23 3423.644159
Ideal 3903 0.20 2597.550090
Premium 2337 0.20 3538.914420
Very Good 2400 0.20 3214.652083
F Fair 312 0.25 3827.003205
Good 909 0.23 3495.750275
Ideal 3826 0.23 3374.939362
Premium 2331 0.20 4324.890176
Very Good 2164 0.23 3778.820240
G Fair 314 0.23 4239.254777
Good 871 0.23 4123.482204
Ideal 4884 0.23 3720.706388
Premium 2924 0.23 4500.742134
Very Good 2299 0.23 3872.753806
H Fair 303 0.33 5135.683168
Good 702 0.25 4276.254986
Ideal 3115 0.23 3889.334831
Premium 2360 0.23 5216.706780
Very Good 1824 0.23 4535.390351
I Fair 175 0.41 4685.445714
Good 522 0.30 5078.532567
Ideal 2093 0.23 4451.970377
Premium 1428 0.23 5946.180672
Very Good 1204 0.24 5255.879568
J Fair 119 0.30 4975.655462
Good 307 0.28 4574.172638
Ideal 896 0.23 4918.186384
Premium 808 0.30 6294.591584
Very Good 678 0.24 5103.513274
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 数据分析--数据处理工具Pandas(2) 的相关文章

  • Python 中的 Hello World [重复]

    这个问题在这里已经有答案了 我尝试运行一个 python 脚本 print Hello World 我收到此错误 File hello py line 1 print Hello World SyntaxError invalid synt
  • 数据框应用不接受轴参数

    我有两个数据框 data and rules gt gt gt data gt gt gt rules vendor rule 0 googel 0 google 1 google 1 dell 2 googly 2 macbook 我正在
  • 整数 numpy 数组乘以浮点数

    我有一个包含整数值的 numpy 数组 如果我将整个矩阵乘以一个浮点数 结果是一个浮点矩阵 但如果我通过 for 循环逐列相乘 它只给出整数部分 import numpy as np A np array 1 2 3 4 5 6 7 8 9
  • 如何使用 pywin32 在 Python 中获取特定应用程序窗口的句柄?

    我正在尝试修改一些在 Windows 10 中截取特定应用程序窗口屏幕截图的 Python 代码 我正在尝试使用win32ui win32guipywin32 包中的模块用于此目的 这是损坏的代码 def getWindow name Wi
  • 从 Windows 文件系统中的任何位置运行 python 脚本

    我已经实现了一些实用程序来满足我的需要 以使用 Python 简化开发 需要多个 py文件和一些额外的 template文件 重命名 txt file 我希望能够从文件系统中的任何位置使用此实用程序 例如 如果我当前位于某个文件夹中 我想运
  • Python select() 行为很奇怪

    我在理解 select select 的行为时遇到一些困难 请考虑以下 Python 程序 def str to hex s def dig n if n gt 9 return chr 65 10 n else return chr 48
  • 十六进制转储文件的Pythonic方式

    我的问题很简单 有什么方法可以用 bash 命令以 Python 方式进行编码吗 hexdump e 2 1 02x file dat 显然 不使用 os popen 或任何快捷方式 编辑 虽然我没有明确指定 但如果代码在 Python3
  • Numpy、Python:广播时自动扩展数组维度

    考虑以下 Numpy 数组广播练习 import numpy as np v np array 1 0 2 0 T column array A2 np random randn 2 10 2D array A3 np random ran
  • 哪个 Python IDE 可以逐行运行我的脚本?

    我不会称自己为程序员 但我最近开始学习 Python 并且非常喜欢它 到目前为止 我主要将它用于小任务 脚本编写 文本处理 KML 生成和 ArcGIS 根据我使用 R 的经验 使用出色的 Notepad 和NppToR http sour
  • 我可以使用 Python 访问 ImageMagick API 吗?

    我需要使用图像魔术师 http www imagemagick org script index php因为 PIL 没有我正在寻找的可用图像功能量 但是 我想使用Python python 绑定 PythonMagick 自 2009 年
  • 为什么 argparse 给我一个列表中的列表?

    我刚刚注意到 argparse 中的一个行为让我困惑 我猜我以前从未将它用于愚蠢的文件列表 import argparse parser argparse ArgumentParser parser add argument multi a
  • 与正在运行的进程通信

    We have 基于Python的服务器 A 正在运行的命令行应用程序 在同一台 Linux 机器上 能够读取stdin 计算一些东西并将输出提供给stdout B 将输入从 A 发送到的最佳 最优雅 方式是什么 stdin B 的 并等待
  • 致命Python错误:init_import_size:无法在Anaconda Prompt中导入站点模块

    当我启动 Anaconda Prompt 时 收到以下错误消息 致命 Python 错误 init import size 无法导入站点模块 Python运行时状态 已初始化回溯 最近一次调用最后一次 文件 C Users blue App
  • 使用 Opencv 屏蔽水平线和垂直线

    我正在尝试删除该图像中的水平线和垂直线 以便拥有更清晰的文本区域 我正在使用下面的代码 它遵循这个guide https docs opencv org 3 2 0 d1 dee tutorial moprh lines detection
  • python 中是否可以有受保护的类变量或方法? [复制]

    这个问题在这里已经有答案了 python 中是否可以有受保护的类变量或方法 我可以看一下这种用法的示例吗 最简洁的答案是不 有一些约定和良好的风格允许您指示某人不应修改这些变量或从类外部调用这些方法 但没有办法严格执行这一点 Python
  • PyPy/RPython 可以用来生成小型独立可执行文件吗?

    或者 可以使用 PyPy RPython 将 Python 编译 翻译为 C C 不需要 Python 运行时 我试图通过它的 RPython 和 Python 它的运行 它的编译和它的翻译来理解 PyPy 但有些失败 I have a h
  • Pythonlibs3 CMake 和 macOS

    更新2 将以下两行添加到我的 CMake 文件中时 成功找到了 python 3 及其库 这只在终端中工作的原因是因为 CLion 使用其捆绑版本的 CMake 3 6 3 而我的终端使用的更新版本 3 7 2 正确找到了 python F
  • 创建将一把小提琴按色调分割的小提琴图的正确方法是什么?

    创建将一把小提琴分开的小提琴图的正确方法是什么hue 我尝试了不同的方法 似乎唯一的方法是创建一个为数据集中的每个条目共享相同值的功能 并将该功能的名称传递为x fig plt figure figsize 20 8 fig add sub
  • Pylance 无法在 VSCode Jupyter 笔记本中工作

    皮兰斯工作于 py files 但不适用于 Jupyter ipynb笔记本 我尝试保存 ipynb 同样的问题 如何在我的笔记本中启用 Pylance 警告 Jupyter 扩展似乎不支持 Pylance 我提交这个问题就是为了解决这个缺
  • “from-import”是否执行整个模块?

    好的 所以我知道from import与 完全 相同import 但这显然不是因为命名空间的填充方式不同 我的问题主要是因为我有一个utils我的应用程序中的每个其他模块都使用一个或两个函数的模块 我正在努力合并标准库logging模块 据

随机推荐

  • Chromium命令行开关列表2

    Chromium命令行开关列表 Google Chrome浏览器可以使用很多命令行 一些更改功能的行为 其他用于调试或试验 该页面列出了可用的开关 包括其条件和说明 上一次自动更新发生在2020 08 12 Condition Explan
  • C51实现流水灯

    文章目录 一 实验要求 二 实验代码和原理图 1 代码 2 原理图 总结 一 实验要求 1 先八盏灯从左至右依次点亮 同一时刻仅有一盏灯处于被点亮状态 每盏灯亮0 5s 然后八盏灯从右至左依次点亮 同一时刻仅有一盏灯处于被点亮状态 每盏灯亮
  • hdu 1074 Doing Homework

    Problem acm hdu edu cn showproblem php pid 1074 题意 n 份作业 分别给出名字 完成所需时间 cost 最迟上交时间 deadline 作业每迟交一天扣一分 问最少的扣分数 Analysis
  • 关于.sln和.suo文件

    sln 和 suo都是是解决方案文件 sln Visual Studio Solution 它通过为环境提供对项目 项目项和解决方案项在磁盘上位置的引用 可将它们组织到解决方案中 包含了较为通用的信息 包括解决方案所包含项目的列表 解决方案
  • TCL foreach的用法

    总结放于前 foreach var list body是foreach的的常见用法 foreach为关键字 var为形参 list为数据容器 数组等 body为函数块 程序每次在程序执行时从list中取到值并赋给形参var 函数块利用var
  • sql外连接内连接

    内连接 两表的交集 符合要求的数据列出来 外连接 左外连接就是查询 join左边表中的所有数据 并且把join右边表中对应的数据查询出来 主表的数据去跟从表一一比较 有就全部列出来 没有就也要列出一条 主表数据全要 他的从表数据变成Null
  • springboot集成Redis

    springboot集成Redis 1 windows平台安装Redis 2 引入依赖 3 修改配置文件 4 启动类添加注解 5 指定缓存哪个方法 6 配置Redis的超时时间 小BUG 测试 对于项目中一些访问量较大的接口 配置上Redi
  • python连接mysql数据库报错pymysql.err.OperationalError

    一 报错信息 pymysql err OperationalError 1045 Access denied for user root localhost using password YES Traceback most recent
  • docker基础:docker stats监控容器资源消耗

    docker stats docker stats 命令用来显示容器使用的系统资源 默认情况下 stats 命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl c 下面是输出的主要内容 CONTAINER 以短格式显示容器的 ID
  • 基于反事实因果推断的度小满额度模型

    本文约4400字 建议阅读9分钟 本文从三个角度与你分享基于反事实因果推断的度小满额度模型 1 因果推断的研究范式 1 相关性与因果性 2 三大基本假设 2 因果推断的框架演进 1 从随机数据到观测数据 2 反事实表示学习 3 反事实额度模
  • 四川百幕晟科技有限公司:抖音没有视频怎么开店铺?

    抖音是中国最受欢迎的短视频平台之一 吸引了数亿用户 很多电商卖家希望利用抖音平台开展业务 但他们可能没有视频资源 幸运的是 抖音还提供了非视频商店功能 允许卖家开设自己的商店并在抖音上推广产品 本文将详细介绍在抖音上开店的步骤 并探讨如何在
  • 破解windows明文密码

    之前看了法国人写的一个软件 mimikatz 可以直接获取windows下的明文密码 简直是丧心病狂 作者已经开源 大家可以去谷歌一下 用SVN下载了源码 是vs2010的工程 然后按照下面命令开始看代码 privilege debug i
  • SQLAlchemy映射已有数据表

    方法一 手动创建数据表模型类进行映射 映射的表必须要有主键 配置数据库连接参数 class Config SQLALCHEMY DATABASE URI mysql pymysql root 123456 localhost 3306 te
  • mysql5.7 免安装版的配置过程

    1 去官网下载mysql 5 7 2 解压压缩包 首先给压缩包重命名一下 修改为你自己想要的 将解压目录下默认文件 my default ini 拷贝一份 改名 my ini 3 修改一下my ini 文件里的内容 client port
  • 基于卷积神经网络结合注意力机制长短记忆网络CNN-LSTM-Attention实现风电功率多输入单输出回归预测附matlab代码

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 更多Matlab仿真内容点击 智能优化算法 神经网络预测 雷达通信 无线传感器 电力系统 信号
  • Kafka安装及测试

    系统环境 Linux Ubuntu 16 04 jdk 7u75 linux x64 相关知识 Kafka是由LinkedIn开发的一个分布式的消息系统 使用Scala编写 它因可以水平扩展和高吞吐率而被广泛使用 目前越来越多的开源分布式处
  • WPF编程,通过Path类型制作沿路径运动的动画另一种方法。

    上一篇文章给了一个这方面的例子 那个文章里是通过后台按钮事件进行动画的开始 停止 继续等 这里给出的是通过前台XAML来实现 1 前台 定义路径 定义运动的主体 这里是一圆
  • IEEE 754 round-to-nearest-even

    IEEE 754 二进制的向偶舍入 舍入的值保证最靠近原浮点数值 如果舍入为中间值 即舍还是入距离相等 那么按其最末尾一位是奇数 则入 如果为偶数 则舍 下面例子说明 xxx yyyyy10000 x为实数任意值 y为任意值 最末尾y为需要
  • 用C++实现简单的小游戏

    采用面向对象的编程思想 在头文件中引入acllic图形库 实现c 控制图片以及生成可视化窗口 所需工具 acllib图形库下载地址 acl图形库下载地址 win32位项目的创建 通过visual studio创建win32项目 三张图片 t
  • python 数据分析--数据处理工具Pandas(2)

    数据处理模块 Pandas 4 Pandas处理字符串和日期数据 5 Pandas 数据清洗 5 1 重复观测处理 5 2 缺失值处理 5 2 1 删除法 5 2 2 替换法 5 3 异常值处理 6 获取数据子集 7 透视表 合并与连接 分