如何溜溜地使用pandas操作数据(一)
注:本文版权由Alfred所有,首发于微信公众号「DataCastle数据城堡」(ID:DataCastle2016),如需转载还请提前联络songdi@datacastle.cn,非常感谢。
Alfred,一个搞数据挖矿的,煎的一手好牛排。曾撰文「一件有趣的事,爬了爬自己的微信朋友圈」被多平台大大大大大大量转载。欢迎你搜狗一下~
如何操作pandas?
用一个实际的数据集练手可能是最快最好的方法。
今天就和大家一起探索pandas关于数据操作和处理的基础方法。
数据来源于DC竞赛的《智慧校园全球大学生创意应用大赛》其中的一个csv文件数据,点击报名参赛便可以获得数据下载链接。本次使用的数据是SiChuanSchool文件夹中的“电子科技大学用户统计-表格 1.csv”文件。
注意
1.运行环境是Python3; 2.由于运行过程中可能有一些结果被我重新编辑或者删去了,所以不要太在意In[ ]的编号顺序; 3.更多更加全面更加正规的使用方法可以阅读pandas的官方文档和《利用Python进行数据分析》(这本书有些方法已经过时了,学习的时候要注意转换); 4.另外,在数据处理的过程中,每一步处理之前先保存好之前的数据是一个良好的习惯,可以免去由于某一步操作错误又要重新处理数据的麻烦。
目录¶
1.导入数据 2.数据初探 3.行/列选取 4.更多行列操作 5.行列删除 6.数据类型的转换 7.数据过滤 8.数据排序 9.数据的描述统计 10.处理缺失的数据 11.数据保存
1.导入数据¶
In [44]:
#首先import pandas
import pandas as pd
In [45]:
#把位于桌面的数据读取进来,由于我用的是Mac,路径可能跟Windows不同
data = pd.read_csv('/Users/apple/Desktop/电子科技大学用户统计-表格 1.csv')
2.数据初探¶
In [46]:
#首先看看数据长什么样子,head()默认获得表格前6行的数据
#也可以在括号里输入想要返回的行数,如data.head(10)返回前10行的数据
#另外有一个需要注意的地方就是,数据导入的时候如果没有特别的参数设置,pandas会自动为数据添加索引,如下面数据框中最左边的0-4就是自动添加的索引
data.head()
Out[46]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/1756632464212571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/17472744518326067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/174608282235330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/174480176245330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771
In [47]:
#使用tail()返回末尾的数据
data.tail(3)
Out[47]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量549226122405911别把过去抱得太紧了无认证普通用户无层级无领域电子科技大学海淀区2/22/17-8549236135533202小名竹子小姐无认证普通用户无层级无领域电子科技大学株洲1900/1/0--549246174296618一件借来的马甲无认证普通用户无层级无领域无教育信息未知4/24/17-667
In [48]:
#有时候由于数据太多,我们不能确定知道了数据的首尾就可以掌握数据的大致情况,
#可以使用sample()来随机抽取出数据中的指定条数,如下随机抽取了5条数据
data.sample(5)
Out[48]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量243313931940541走向尽头_19021无认证普通用户无层级无领域无教育信息成都1900/1/0-115397625602246379泰陵玑衡无认证普通用户无层级无领域电子科技大学西安1900/1/0-NaN40131796225561二大神无认证普通用户无层级无领域郑州大学郑州6/12/1716156153735736564432to挑衅本尊无认证普通用户无层级无领域电子科技大学巴中5/15/17127286615688941824时间肯定好无认证普通用户无层级无领域电子科技大学成都1/15/17-63
In [49]:
#查看数据有多少行多少列,注意shape后面不带括号
data.shape
#可以看到数据有54925行,11列
Out[49]:
(54925, 11)
In [50]:
#查看数据的列名
data.columns
Out[50]:
Index(['UID', '昵称', '认证信息', 'v区分', '层级', '领域', '教育信息', '城市', '最近发博时间', '发博量',
'粉丝量'],
dtype='object')
In [51]:
#使用describe()返回数据描述性统计的值:count(计数),mean(平均值),std(标准差),min(最小值),25%(Q1四分位数),50%(Q2四分位数,即中位数),75%(Q3四分位数),max(最大值)
data.describe()
Out[51]:
UIDcount5.492500e+04mean3.744216e+09std1.540637e+09min1.048020e+0525%2.395101e+0950%3.303743e+0975%5.384490e+09max6.278296e+09
In [52]:
#奇怪了,明明“发博量”和“粉丝量”字段都是数值型数据啊,为什么只返回了“UID”的统计?
#使用info看一下各个字段被读取进来的时候的数据类型
data.info()
#可以看到数据读取进来的时候,“UID”被识别成了int型,其他都被默认识别成object
#这就涉及到数据类型的转换,后面会讲到,先跳过(先来学习一些基础知识)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54925 entries, 0 to 54924
Data columns (total 11 columns):
UID 54925 non-null int64
昵称 54671 non-null object
认证信息 54925 non-null object
v区分 54925 non-null object
层级 54925 non-null object
领域 54925 non-null object
教育信息 54925 non-null object
城市 54921 non-null object
最近发博时间 54889 non-null object
发博量 54925 non-null object
粉丝量 53900 non-null object
dtypes: int64(1), object(10)
memory usage: 4.6+ MB
3.行/列选取¶
In [53]:
#如果想要获得指定位置的某条记录,比如索引号为666的记录,可以使用:
data.loc[666]
#其实就是行选取
Out[53]:
UID 3044329831
昵称 左道幽氳
认证信息 无认证
v区分 普通用户
层级 无层级
领域 无领域
教育信息 无教育信息
城市 成都
最近发博时间 6/13/17
发博量 108
粉丝量 80
Name: 666, dtype: object
In [54]:
#想要获取666-668的记录,使用:
data.loc[666:668]
#注意和data[666:668]的区别(自行实现对比一下)
Out[54]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量6663044329831左道幽氳无认证普通用户无层级无领域无教育信息成都6/13/17108806675792376745我叫小笑子无认证普通用户无层级无领域电子科技大学未知6/11/17108636685172765695易二八无认证普通用户无层级无领域无教育信息成都6/13/1710832
In [55]:
#想要获取666,777,888的记录,使用:
data.loc[[666,777,888]]
Out[55]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量6663044329831左道幽氳无认证普通用户无层级无领域无教育信息成都6/13/17108807771313468125吖呀飞扬无认证普通用户无层级无领域西北农林科技大学成都6/13/17931108882026953081Mr_北极bear无认证普通用户无层级无领域电子科技大学长春6/13/1781534
In [56]:
#想要获取特定列(字段)的记录,比如“昵称”列,:
data['昵称']
Out[56]:
0 小仙女tracy遇见幸福
1 彩票老聂
2 淘折扣-帮帮VIP
3 教你品味穿衣
4 张戎强_15565
5 张宸hgh
6 -融融团儿-
7 上海吃喝玩乐嗨
8 幸福女人有心计
9 mickey-fang
10 电影攻略菌
11 精选星座微博
12 超搞笑集中营
13 嘉妈嘉妈
14 母婴育儿店
15 骑驴跑
16 电子科技大学微博协会
17 电子科技大学微博协会
18 电子科技大学微博协会
19 电子科技大学微博协会
20 KSH-小小飞719
21 我叫易只烊
22 买一张琴
23 海外生活伦敦
24 DIY设计家居馆
25 毛裤团
26 歌-木木-朵
27 爱西瓜的小小美女
28 亲爱的哦你哦赛哟
29 笑掉大牙
...
54895 雪融花开了
54896 love旭弟弟
54897 带你去看hanabi
54898 雨季不等于阳光
54899 微商快手团队
54900 yiyu你好
54901 yiyu你好
54902 兰色的萧陌
54903 纵容你侵占我的板涂
54904 溺氧绿植
54905 Deja___Cool
54906 安Licy明
54907 Y志明_
54908 周洪均70780
54909 霸道总裁-夏琳琳
54910 我像孩紙一樣守著回憶
54911 你猜6059312516
54912 渴望JS友谊
54913 H阿雨雨雨雨
54914 铲屎官故事
54915 阿超_015
54916 从来只有我调戏别人
54917 吉39498
54918 秦林林rain
54919 我真的不是罗辑
54920 信不信我只手遮你胸
54921 陈笑天200702
54922 别把过去抱得太紧了
54923 小名竹子小姐
54924 一件借来的马甲
Name: 昵称, Length: 54925, dtype: object
In [57]:
#获取多列的记录,传入一个列表:
data[['昵称','认证信息']]
Out[57]:
昵称认证信息0小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员1彩票老聂微电商达人2淘折扣-帮帮VIP无认证3教你品味穿衣司瓦特(杭州)能源科技有限公司经理4张戎强_15565深圳市事必成电子有限公司财务5张宸hgh杭州慎思行广告策划有限公司广告企划6-融融团儿-无认证7上海吃喝玩乐嗨天娱文化传媒有限公司歌手8幸福女人有心计微博情感帐号9mickey-fang深圳淘商网络科技有限公司人力资源总监10电影攻略菌三只狐狸影评人11精选星座微博知名星座命理博主12超搞笑集中营知名搞笑幽默博主13嘉妈嘉妈无认证14母婴育儿店无认证15骑驴跑无认证16电子科技大学微博协会电子科技大学微博协会官方微博17电子科技大学微博协会电子科技大学微博协会官方微博18电子科技大学微博协会电子科技大学微博协会官方微博19电子科技大学微博协会电子科技大学微博协会官方微博20KSH-小小飞719无认证21我叫易只烊无认证22买一张琴无认证23海外生活伦敦无认证24DIY设计家居馆家居撰稿人25毛裤团成都愉悦科技有限公司职员26歌-木木-朵无认证27爱西瓜的小小美女惠州市国创电子有限公司客户经理28亲爱的哦你哦赛哟通力电子控股有限公司 工程师29笑掉大牙无认证.........54895雪融花开了无认证54896love旭弟弟无认证54897带你去看hanabi无认证54898雨季不等于阳光无认证54899微商快手团队无认证54900yiyu你好无认证54901yiyu你好无认证54902兰色的萧陌无认证54903纵容你侵占我的板涂无认证54904溺氧绿植无认证54905Deja___Cool无认证54906安Licy明无认证54907Y志明_无认证54908周洪均70780无认证54909霸道总裁-夏琳琳无认证54910我像孩紙一樣守著回憶无认证54911你猜6059312516无认证54912渴望JS友谊无认证54913H阿雨雨雨雨无认证54914铲屎官故事无认证54915阿超_015无认证54916从来只有我调戏别人无认证54917吉39498无认证54918秦林林rain无认证54919我真的不是罗辑无认证54920信不信我只手遮你胸无认证54921陈笑天200702无认证54922别把过去抱得太紧了无认证54923小名竹子小姐无认证54924一件借来的马甲无认证
54925 rows × 2 columns
In [58]:
#获取字段“昵称”,“认证信息”的前11行的记录
data.loc[:10,['昵称','认证信息']]
#注意观察代码,逗号前面指定行,逗号后面指定列
Out[58]:
昵称认证信息0小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员1彩票老聂微电商达人2淘折扣-帮帮VIP无认证3教你品味穿衣司瓦特(杭州)能源科技有限公司经理4张戎强_15565深圳市事必成电子有限公司财务5张宸hgh杭州慎思行广告策划有限公司广告企划6-融融团儿-无认证7上海吃喝玩乐嗨天娱文化传媒有限公司歌手8幸福女人有心计微博情感帐号9mickey-fang深圳淘商网络科技有限公司人力资源总监10电影攻略菌三只狐狸影评人
In [59]:
#获取前5行,第9-11列的数据
data.iloc[:5,8:]
#注意loc和iloc的区别
Out[59]:
最近发博时间发博量粉丝量06/13/1756632464216/13/17472744518326/13/174608282236/13/174480176246/13/1737811771
4.更多行列操作¶
In [60]:
#在数据表中新增一列“test”,赋值为NaN(缺失值)
#首先把numpy导入进来,因为要用到numpy的缺失值nan
import numpy as np
data['test'] = np.nan
#好了,看一下现在的数据长什么样子,可以看到最右边已成功添加一列“test”,值为NaN
data.head()
Out[60]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量test01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642NaN12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183NaN26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822NaN35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762NaN45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771NaN
In [61]:
#把“test”列重新赋值为999
data['test'] = 999
#瞅一眼数据
data.head()
Out[61]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量test01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/1756632464299912571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/17472744518399926067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/174608282299935330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/174480176299945330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771999
In [62]:
#把“test”列按照规则赋值:每条记录的“v区分”字段是否是“橙V”
data['test'] = data.v区分 == '橙V'
#瞅一眼数据。data.v区分 == '橙V'返回的是一串boolean值True/False,如果是“橙V”则为True,否则是False
data.head()
Out[62]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量test01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642True12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183True26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822False35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762True45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771True
In [63]:
#于是结合上面的方法,可以这样来赋值:
#如果是'橙V'便赋值为'这丫竟是橙V,大家快来孤立他!',如果不是'橙V'便赋值为'辛亏不是橙V'
data.loc[data.v区分 == '橙V','test'] = '这丫竟是橙V,大家快来孤立他!'
data.loc[data.v区分 != '橙V','test'] = '辛亏不是橙V'
#再瞅一眼数据
data.head()
Out[63]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量test01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822辛亏不是橙V35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762这丫竟是橙V,大家快来孤立他!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771这丫竟是橙V,大家快来孤立他!
In [64]:
#于是,由上面的方法可以引出,如果要想给数据特定的位置赋值,比如想要把‘test’列的2-4行赋值为“我不听我不听!”,可以这样:
data.loc[2:4,'test'] = '我不听我不听!'
data.head()
Out[64]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量test01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822我不听我不听!35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!
In [65]:
#如果想要更改某列的列名,怎么做呢?
data.rename(columns={'test':'乱加的一列'}, inplace = True)
#使用rename,指定columns,使用字典mapping(映射)的方法改变,记得加上inplace=True,表示直接在数据表data上固化这个操作
data.head()
Out[65]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822我不听我不听!35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!
In [66]:
#如果想要更改所有的列名,怎么做呢?
#为了不直接在data数据集上更改,新起一个只包含data数据表中前6行的数据表data_test
data_test=data[:6]
#使用直接传入一个列表的方式更改,这里把它改为['列1','列2','列3','列4','列5','列6','列7','列8','列9','列10','列11','列12']
#这种方法要求列表中的列名顺序必须与原数据一致,还有一种方法是使用上面的字典mapping(映射),大家可以思考一下怎么操作。
data_test.columns=['列1','列2','列3','列4','列5','列6','列7','列8','列9','列10','列11','列12']
data_test
Out[66]:
列1列2列3列4列5列6列7列8列9列10列11列1201363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822我不听我不听!35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!55330513605张宸hgh杭州慎思行广告策划有限公司广告企划橙VC3无领域无教育信息未知6/13/1737631911这丫竟是橙V,大家快来孤立他!
In [67]:
#列按照列名重新排列:比如说,你觉得现在每列的排列你看起来很不爽,想要把列4排在列3的前面,列8排在列7的前面,列12排在列4的后面,怎么做?
#使用reindex,指定是针对columns
data_test.reindex(columns=['列1','列2','列4','列12','列3','列5','列6','列8','列7','列9','列10','列11'])
Out[67]:
列1列2列4列12列3列5列6列8列7列9列10列1101363172732小仙女tracy遇见幸福橙V这丫竟是橙V,大家快来孤立他!百胜咨询(上海)有限公司采购专员C5美食徐汇区同济大学6/13/1756632464212571350940彩票老聂橙V这丫竟是橙V,大家快来孤立他!微电商达人C2电商成都四川师范大学6/13/17472744518326067613738淘折扣-帮帮VIP普通用户我不听我不听!无认证C3无领域南充电子科技大学6/13/174608282235330304545教你品味穿衣橙V我不听我不听!司瓦特(杭州)能源科技有限公司经理C3无领域未知无教育信息6/13/174480176245330304450张戎强_15565橙V我不听我不听!深圳市事必成电子有限公司财务C3无领域未知无教育信息6/13/173781177155330513605张宸hgh橙V这丫竟是橙V,大家快来孤立他!杭州慎思行广告策划有限公司广告企划C3无领域未知无教育信息6/13/1737631911
In [68]:
#行按照索引重新排列,同样是使用reindex,如果不明确指定是针对index还是columns,默认操作是针对index
#当然也可以使用data_test.reindex(index = [3,4,5,0,1,2])明确指定,让代码更具有可读性
data_test.reindex([3,4,5,0,1,2])
Out[68]:
列1列2列3列4列5列6列7列8列9列10列11列1235330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!55330513605张宸hgh杭州慎思行广告策划有限公司广告企划橙VC3无领域无教育信息未知6/13/1737631911这丫竟是橙V,大家快来孤立他!01363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!26067613738淘折扣-帮帮VIP无认证普通用户C3无领域电子科技大学南充6/13/1746082822我不听我不听!
5.行列删除¶
In [69]:
#删除特定的行,比如说想要删除第2,第5行
data_test.drop([2,5], axis=0)
#注意,如果想要固化删除这个操作,需要使用data_test = data_test.drop([2,5], axis=0)或者加上inplace=True
Out[69]:
列1列2列3列4列5列6列7列8列9列10列11列1201363172732小仙女tracy遇见幸福百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!12571350940彩票老聂微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!35330304545教你品味穿衣司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!45330304450张戎强_15565深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!
In [70]:
#同样,想要删除特定列,可以使用:
data_test.drop(['列1','列2'], axis = 1)
#axis=0表示行所在的轴,axis=1表示列所在的轴
Out[70]:
列3列4列5列6列7列8列9列10列11列120百胜咨询(上海)有限公司采购专员橙VC5美食同济大学徐汇区6/13/17566324642这丫竟是橙V,大家快来孤立他!1微电商达人橙VC2电商四川师范大学成都6/13/174727445183这丫竟是橙V,大家快来孤立他!2无认证普通用户C3无领域电子科技大学南充6/13/1746082822我不听我不听!3司瓦特(杭州)能源科技有限公司经理橙VC3无领域无教育信息未知6/13/1744801762我不听我不听!4深圳市事必成电子有限公司财务橙VC3无领域无教育信息未知6/13/1737811771我不听我不听!5杭州慎思行广告策划有限公司广告企划橙VC3无领域无教育信息未知6/13/1737631911这丫竟是橙V,大家快来孤立他!
6.数据类型的转换¶
In [71]:
#有了前面的基础知识,现在我们回到一开始的数据类型的问题。
#先看“发博量”字段,首先使用data['发博量']或者data['发博量'].sample(10)瞅一眼数据
data['发博量'].sample(10)
#发现数据之所以会在导入时被默认成object,是因为中间不只有数值型数据,还有“-”,代表缺失数据或者代表发博量为0
#到底“-”代表的是缺失数据或还是发博量为0呢?原数据没有给出太多的说明,这值得我们深究,以决定到底使用什么方法处理这个数据(直接丢弃/替换成NaN/替换成0/...)。
Out[71]:
53236 8
52739 1
13076 2
49368 -
1012 72
32042 -
37684 77
30341 -
38588 -
47448 1
Name: 发博量, dtype: object
In [72]:
#现先认为“-”代表的是发博量为0,那么需要把“-”替换成0
data.loc[data.发博量 == '-','发博量'] = 0
#瞅一眼数据,可以发现“-”已被成功替换成0
data['发博量'].sample(10)
Out[72]:
38326 0
23459 0
13043 2
24271 0
3742 18
8729 5
33859 0
16892 0
9112 5
28672 0
Name: 发博量, dtype: object
In [73]:
#接下来就可以进行数据类型的转换啦
data.发博量 = pd.to_numeric(data.发博量)
#查看数据类型,可以发现“发博量”的数据类型已成功被更改为int(64)
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54925 entries, 0 to 54924
Data columns (total 12 columns):
UID 54925 non-null int64
昵称 54671 non-null object
认证信息 54925 non-null object
v区分 54925 non-null object
层级 54925 non-null object
领域 54925 non-null object
教育信息 54925 non-null object
城市 54921 non-null object
最近发博时间 54889 non-null object
发博量 54925 non-null int64
粉丝量 53900 non-null object
乱加的一列 54925 non-null object
dtypes: int64(2), object(10)
memory usage: 5.0+ MB
In [75]:
#同样的方法处理一下“粉丝量”字段
#思考一下,如果不替换“-”,直接使用pd.to_numeric会出现什么状况?怎么处理?(自行操作一下,提示:去查找一下pd.to_numeric更加全面的用法,以及data.粉丝量 = pd.to_numeric(data.粉丝量, errors='coerce')这段代码的含义)
data.loc[data.粉丝量 == '-','粉丝量'] = 0
data.粉丝量 = pd.to_numeric(data.粉丝量)
#看一眼数据,发现“粉丝量”被处理成了float64,大家可以思考一下为什么,以及怎么处理?
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54925 entries, 0 to 54924
Data columns (total 12 columns):
UID 54925 non-null int64
昵称 54671 non-null object
认证信息 54925 non-null object
v区分 54925 non-null object
层级 54925 non-null object
领域 54925 non-null object
教育信息 54925 non-null object
城市 54921 non-null object
最近发博时间 54889 non-null object
发博量 54925 non-null int64
粉丝量 53900 non-null float64
乱加的一列 54925 non-null object
dtypes: float64(1), int64(2), object(9)
memory usage: 5.0+ MB
In [76]:
#同样需要处理的还有“最近发博时间”字段,把object型转换成datetime型
#首先看一眼数据的基本情况,可以发现数据存储的格式是月/日/年,但是还有一个异常数据,那就是“1900/1/0”,这个可以定为缺失数据
data.最近发博时间.sample(10)
Out[76]:
25646 11/15/14
27111 4/22/17
34361 1900/1/0
24765 4/3/16
8697 6/2/17
17539 11/6/16
482 6/13/17
1069 6/13/17
9142 6/13/17
30067 7/2/16
Name: 最近发博时间, dtype: object
In [77]:
#直接使用pd.to_datetime转换,对于时间是“1900/1/0”的直接转换成NaT
data.最近发博时间 = pd.to_datetime(data['最近发博时间'], errors='coerce')
In [78]:
#相信你已经注意到上面的代码中我混用了“data.最近发博时间”和“data['最近发博时间']”,请自行去了解一下
#瞅一眼数据,可以发现数据已被成功转换成datetime64型,“1900/1/0”也被成功转换成NaT
data.最近发博时间.sample(10)
Out[78]:
33568 2017-02-03
14491 2017-05-14
19072 2017-03-16
34038 NaT
52733 2017-01-26
9495 2017-06-13
13303 2017-06-09
34718 2014-11-15
23843 2016-05-31
45007 NaT
Name: 最近发博时间, dtype: datetime64[ns]
7.数据过滤¶
In [80]:
#前面已经涉及了一些数据过滤的操作了,这里再深入一些探究
#假如我只想选取粉丝量大于1000000的微博记录(由于数据有75条,太多了不好显示,所以我加了head()):
data[data['粉丝量']>1000000].head()
Out[80]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列72912165441上海吃喝玩乐嗨天娱文化传媒有限公司歌手橙VC3美食无教育信息未知2017-06-1335001855222.0这丫竟是橙V,大家快来孤立他!82203959564幸福女人有心计微博情感帐号橙VC1情感两性中国科学院大学广州2017-06-1329472048157.0这丫竟是橙V,大家快来孤立他!103947532062电影攻略菌三只狐狸影评人橙VC1电影常熟理工学院台北市2017-06-1328878263459.0这丫竟是橙V,大家快来孤立他!112484832905精选星座微博知名星座命理博主橙VC1星座命理无教育信息未知2017-06-13272010068055.0这丫竟是橙V,大家快来孤立他!121921208427超搞笑集中营知名搞笑幽默博主橙VC1搞笑幽默无教育信息未知2017-06-13264517380052.0这丫竟是橙V,大家快来孤立他!
In [81]:
#选取粉丝量在1000000到1200000之间的数据
data[(data['粉丝量']>1000000) & (data['粉丝量']<1200000)]
#这里可以看到,有些微博发博量那么小竟然有那么多的粉丝,这让我开始质疑这里的发博量是怎么统计的,以及数据真实性,这个原因值得我们探寻。当然这是外话,暂且按下不表。
Out[81]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列601974945511Marco_徐晓峰上海览领资产管理有限公司董事长兼总裁橙VC1财经无教育信息浦东新区2017-06-139891030818.0这丫竟是橙V,大家快来孤立他!2781996808583中国移动广西公司中国移动通信集团广西有限公司蓝V无层级无领域无教育信息未知2017-06-132451045645.0辛亏不是橙V9402219368761搜狐视频移动客户端搜狐视频移动客户端官方微博蓝VC2综艺节目无教育信息未知2017-06-13771166605.0辛亏不是橙V12132802767157睿皓客服广州市睿皓投资管理有限公司蓝V无层级无领域无教育信息未知2017-06-10601112197.0辛亏不是橙V166983504492202财经新闻观察员yojo鼎盟资产管理有限公司 项目经理橙VC5无领域无教育信息东城区2017-04-2701003491.0这丫竟是橙V,大家快来孤立他!167373296184181创意设计师--Lucy鸿展广告印务有限公司 平面设计橙VC5设计美学无教育信息徐汇区2017-04-2701002837.0这丫竟是橙V,大家快来孤立他!
In [82]:
#假如说我对于不是大V(也就是普通用户)同时粉丝量又大于100万的微博感兴趣,如何选取呢?
#到了这一步,我想要谈一谈数据过滤操作的原理:data['粉丝量']>1000000返回的是一串boolean值(True/False),大于100万的为True,小于或等于100万的为False,再把这串boolean值传入data[]进行数据选取,返回对应值为True的记录
#符号“&”是“且”的意思,表示只有两个条件同时满足才会返回True,否则返回False
#或且非:“|”是“或”的意思,“&”是“且”的意思,“!=”是“非”的意思,可以自行实现看看
data[(data['粉丝量']>1000000) & (data['v区分'] == '普通用户')]
Out[82]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列592155487004热门奇事趣闻无认证普通用户C1搞笑幽默无教育信息广州2017-06-1310082478912.0辛亏不是橙V3262092488475萌死你不负责无认证普通用户C1动物宠物无教育信息未知2017-06-132144077139.0辛亏不是橙V80742822792812小女子爱靓妆无认证普通用户C5时尚逢甲大學石家庄2017-06-0662047280.0辛亏不是橙V80752822792812小女子爱靓妆无认证普通用户C5时尚解放军艺术学院石家庄2017-06-0662047280.0辛亏不是橙V100881650434880热门百科搜罗无认证普通用户C4科学科普无教育信息朝阳区2017-06-1345413067.0辛亏不是橙V262072912473701奥舒小铺无认证普通用户C5美妆无教育信息海淀区2016-09-2303038936.0辛亏不是橙V391873089575472爱美女人宝典无认证普通用户C4美妆无教育信息南京2017-06-01311089043.0辛亏不是橙V440832092275377IT科技全知道无认证普通用户C5数码无教育信息佛山2016-12-2101619559.0辛亏不是橙V
In [83]:
#再在前面的基础上添上一个条件:层级不是“C5”的
data[(data['粉丝量']>1000000) & (data['v区分'] == '普通用户') & (data['层级'] != 'C5')]
Out[83]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列592155487004热门奇事趣闻无认证普通用户C1搞笑幽默无教育信息广州2017-06-1310082478912.0辛亏不是橙V3262092488475萌死你不负责无认证普通用户C1动物宠物无教育信息未知2017-06-132144077139.0辛亏不是橙V100881650434880热门百科搜罗无认证普通用户C4科学科普无教育信息朝阳区2017-06-1345413067.0辛亏不是橙V391873089575472爱美女人宝典无认证普通用户C4美妆无教育信息南京2017-06-01311089043.0辛亏不是橙V
8.数据排序¶
In [84]:
#观察数据发现,数据应该是按照发博量降序的,假如我想按照“粉丝量”排序,可以使用sort_values(),把想要排序的列传值给by:
#注意,这里为了更好显示还是使用了head()
data.sort_values(by='粉丝量').head()
Out[84]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列393865801712160Z崔廷松TI无认证普通用户无层级无领域电子科技大学临沂2016-03-1400.0辛亏不是橙V286335580676423csm小玉_625无认证普通用户无层级无领域电子科技大学未知NaT00.0辛亏不是橙V286315576825313就是何小猪_58282无认证普通用户无层级无领域电子科技大学成都NaT00.0辛亏不是橙V197405241977690MISS韓小艾L无认证普通用户无层级无领域无教育信息成都2016-03-0600.0辛亏不是橙V469835787419079取名字都被取完了无认证普通用户无层级无领域电子科技大学金华NaT00.0辛亏不是橙V
In [87]:
#哎呀妈呀,默认的是升序排列,我想要的是按照“粉丝量”降序排列,所以需要加上ascending=False
#选取数据表中粉丝量最多的前5个微博
data.sort_values(by='粉丝量',ascending=False).head()
Out[87]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列391663072851中国日报中国日报官方微博蓝VC1媒体无教育信息未知2017-06-13147827477245.0辛亏不是橙V121921208427超搞笑集中营知名搞笑幽默博主橙VC1搞笑幽默无教育信息未知2017-06-13264517380052.0这丫竟是橙V,大家快来孤立他!942316673484每日幽默趣事知名搞笑幽默博主橙VC1搞笑幽默无教育信息东城区2017-06-1368112263190.0这丫竟是橙V,大家快来孤立他!83053090413830时尚生活女郎网时尚生活女郎网官方微博蓝V无层级无领域清华大学黄浦区2017-06-05511582338.0辛亏不是橙V391873089575472爱美女人宝典无认证普通用户C4美妆无教育信息南京2017-06-01311089043.0辛亏不是橙V
In [88]:
#假如我想要首先按照“最近发博时间”降序排序,“最近发博时间”相同的情况下再按照“粉丝量”降序排序,应该怎么做?
#此时只需要传给by一个列表就好啦
data.sort_values(by=['最近发博时间','粉丝量'],ascending=False).head()
Out[88]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列391663072851中国日报中国日报官方微博蓝VC1媒体无教育信息未知2017-06-13147827477245.0辛亏不是橙V121921208427超搞笑集中营知名搞笑幽默博主橙VC1搞笑幽默无教育信息未知2017-06-13264517380052.0这丫竟是橙V,大家快来孤立他!942316673484每日幽默趣事知名搞笑幽默博主橙VC1搞笑幽默无教育信息东城区2017-06-1368112263190.0这丫竟是橙V,大家快来孤立他!112484832905精选星座微博知名星座命理博主橙VC1星座命理无教育信息未知2017-06-13272010068055.0这丫竟是橙V,大家快来孤立他!103947532062电影攻略菌三只狐狸影评人橙VC1电影常熟理工学院台北市2017-06-1328878263459.0这丫竟是橙V,大家快来孤立他!
In [89]:
#另外需要注意的是在排序时,缺失值会被默认放在最后,看看这个按照“粉丝量”降序排序的数据末尾都是粉丝量为NaN的
data.sort_values(by='粉丝量',ascending=False).tail()
Out[89]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列547675255416206用户5255416206无认证普通用户无层级无领域无教育信息未知2015-01-040NaN辛亏不是橙V548205554815685时光暖心掘用无认证普通用户无层级无领域电子科技大学未知NaT0NaN辛亏不是橙V548605754177219NaN无认证普通用户无层级无领域无教育信息NaNNaT0NaN辛亏不是橙V548745809538378夏商丶无认证普通用户无层级无领域电子科技大学成都2017-06-085NaN辛亏不是橙V548835848764247郭局辰郭无认证普通用户无层级无领域电子科技大学百色NaT0NaN辛亏不是橙V
9.数据的描述统计¶
In [92]:
#前面已经使用过describe()返回描述统计值,再看看sum(总和),mean(平均值),median(中值),std(标准差),count(计数),min(最小值),max(最大值),quantile(分位数)各自的操作
#以“粉丝量字段”为例,求粉丝量平均数,其他的同理
data['粉丝量'].mean()
Out[92]:
6821.6289795918365
In [93]:
#有一点需要注意的地方就是,mean()会自动跳过缺失值(NaN),也就是说使用mean()计算出来的平均值是以“粉丝量”字段中非NaN值为基础的
#可以看看如果是以总体记录数为基础计算平均数,数值上的差别
data['粉丝量'].sum()/len(data['粉丝量'])
Out[93]:
6694.3250250341371
In [94]:
#还有一个比较有用的操作是idxmin(返回最小值的索引),idxmax(返回最大值的索引)
#返回粉丝量最大的微博所在的索引,这里返回索引39
data['粉丝量'].idxmax()
Out[94]:
39
In [95]:
#可以根据索引号把最大值所在的记录调出来看看,原来是“中国日报”
data.loc[data['粉丝量'].idxmax()]
Out[95]:
UID 1663072851
昵称 中国日报
认证信息 中国日报官方微博
v区分 蓝V
层级 C1
领域 媒体
教育信息 无教育信息
城市 未知
最近发博时间 2017-06-13 00:00:00
发博量 1478
粉丝量 2.74772e+07
乱加的一列 辛亏不是橙V
Name: 39, dtype: object
In [96]:
#计算两列的相关系数
#假设:“发博量”与“粉丝量”是正相关的,使用corr计算相关系数
#可以看到返回的相关系数还是比较低的,其中的原因值得我们探讨
data.发博量.corr(data.粉丝量)
Out[96]:
0.21983301162949223
In [97]:
#从data.head()中可以看到“层级”字段的值有C5,C2,C3等,我想知道“层级“字段都包含有哪些值,使用unique
#可以看到“层级”字段包含['C5', 'C2', 'C3', '无层级', 'C1', 'C4']等
data.层级.unique()
Out[97]:
array(['C5', 'C2', 'C3', '无层级', 'C1', 'C4'], dtype=object)
In [98]:
#假如我想看看每个层级都有多少条记录,也就是计算每个层级的频数
data.层级.value_counts()
Out[98]:
无层级 52131
C5 2134
C4 379
C3 163
C1 65
C2 53
Name: 层级, dtype: int64
10.处理缺失的数据¶
In [99]:
#前面已经穿插了一些缺失数据处理的内容,现在再深入一下来探讨
#为了简化说明,现在根据data这个数据集执行以下操作,构造一个简化的数据集data_test
data_test = data.sample(6)
data_test.loc[data_test['发博量']==0,'发博量']=np.nan
data_test.loc[44942]=np.nan
#瞅一眼这个构造好的数据集data_test
data_test
Out[99]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户无层级无领域电子科技大学成都2017-04-11NaN59.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户无层级无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-13NaN10.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-23NaN4.0辛亏不是橙V44942NaNNaNNaNNaNNaNNaNNaNNaNNaTNaNNaNNaN
In [100]:
#丢弃所有包含缺失数据的行(只要一行中包含一个缺失数据,即丢弃):
data_test.dropna()
Out[100]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列148185.574223e+09今天天气不错挖无认证普通用户无层级无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V
In [101]:
#dropna()默认丢弃所有包含缺失数据的行,如果我只想要丢弃44942行(一行数据的所有字段值都是NaN),其他都保留,需要使用一个参数how,把“all”传值给how,表示只有全是NaN值的记录才会被丢弃
#这里使用inplace=True固化删除44942行这个操作,因为下面的操作需要使用到这个结果
data_test.dropna(how='all',inplace=True)
#瞅一眼数据,可以发现只有原来的44942行被丢弃了
data_test
Out[101]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户无层级无领域电子科技大学成都2017-04-11NaN59.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户无层级无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-13NaN10.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-23NaN4.0辛亏不是橙V
In [102]:
#丢弃包含缺失数据的列(这个方法不常用到,了解一下就好)
data_test.dropna(axis = 1)
#可以发现包含NaN的“发博量”一列被删除了
Out[102]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户无层级无领域电子科技大学成都2017-04-1159.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户无层级无领域无教育信息未知2017-06-0951.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-03131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-1310.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-0944.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-234.0辛亏不是橙V
In [104]:
#如果决定处理缺失数据的方式不是直接丢弃,而是填充数据
#为了更好地说明操作方法,再构造一下数据集
data_test.loc[44942]=np.nan
data_test.loc[[49334,14818],'层级'] = np.nan
#瞅一眼数据长什么样子
data_test
Out[104]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户NaN无领域电子科技大学成都2017-04-11NaN59.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户NaN无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-13NaN10.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-23NaN4.0辛亏不是橙V44942NaNNaNNaNNaNNaNNaNNaNNaNNaTNaNNaNNaN
In [105]:
#好,接下来就可以进行填充缺失数据的操作了:填充数据使用的是fillna()方法,括号里传入填充的方法
#假如我想要把所有的缺失数据都填充为0,则在括号里直接传入0:
#可以看到所有的缺失数据都被成功填充为0(可能这里你就要怼我了:明明最后一行的最近发博时间没有被填充为0啊,其实,计算机默认的时间起点就是“1970-01-01”)
data_test.fillna(0)
Out[105]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户0无领域电子科技大学成都2017-04-110.059.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户0无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-130.010.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-230.04.0辛亏不是橙V449420.000000e+0000000001970-01-010.00.00
In [106]:
#假如我想要给每一列的缺失数据填充不一样的值,比如说给“层级”列填充“C0”,给“发博量”填充“999”,则传入一个字典mapping(映射)
data_test.fillna({'层级':'C0','发博量':'999'})
Out[106]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户C0无领域电子科技大学成都2017-04-1199959.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户C0无领域无教育信息未知2017-06-09151.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-1399910.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-09144.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-239994.0辛亏不是橙V44942NaNNaNNaNNaNC0NaNNaNNaNNaT999NaNNaN
In [108]:
#给发博量的缺失数据直接赋值为“999”真是太草率了,如果我想按照发博量的平均值填充缺失数据,则:
data_test['发博量'].fillna(data['发博量'].mean())
#因为data_test数据集的发博量都是1,所以我使用了原数据集data的发博量平均值来填充了
Out[108]:
49334 11.062503
14818 1.000000
16033 1.000000
21157 11.062503
51906 1.000000
46397 11.062503
44942 11.062503
Name: 发博量, dtype: float64
In [109]:
#还有一种方法是向前填充(forward fill),这种填充方法很经常用在时间序列的缺失值填充里,这里只是利用这个数据集举个例
#向前填充的意思就是每行的实值往前(下)填充缺失值,比如说原来的数据中46397行的“发博量”为NaN值,就被上一行(51906行)的值向前填充了,如果下一行的“发博量”还是缺失值,还会继续往前填充
#由于49334行的“发博量”上面没有数据可以实现向前填充,所以使用ffill之后它的值还是NaN
#类似的方法还有向后填充(back fill),可以自行操作代码data_test.fillna(method='bfill')看看
data_test.fillna(method='ffill')
Out[109]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户NaN无领域电子科技大学成都2017-04-11NaN59.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户NaN无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-131.010.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-231.04.0辛亏不是橙V449425.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-231.04.0辛亏不是橙V
In [110]:
#这种填充方法有一个bug,就是万一数据连着10行都是缺失数据的话,那么使用ffill的方法填充的话这10行缺失数据都会被填充成上面一行有实值的数据,这样的填充方法很不准确,比如说如果是时间序列数据的话,前一天和后一天的数据可能是有强相关的,可是有时相隔10天的数据差别是很大的。
#为此,有一个限定最大连续填充行数的方法limit,假如我想要限定往下填充只允许填充一行,则:
data_test.fillna(method='ffill',limit=1)
#可以发现,这种填充方法的话,44942行的“发博量”值就没有被连续填充
Out[110]:
UID昵称认证信息v区分层级领域教育信息城市最近发博时间发博量粉丝量乱加的一列493343.501844e+09随遇而安SYG无认证普通用户NaN无领域电子科技大学成都2017-04-11NaN59.0辛亏不是橙V148185.574223e+09今天天气不错挖无认证普通用户NaN无领域无教育信息未知2017-06-091.051.0辛亏不是橙V160331.598527e+09pi21无认证普通用户无层级无领域电子科技大学成都2017-06-031.0131.0辛亏不是橙V211572.836428e+09修身520无认证普通用户无层级无领域大竹二中福州2016-11-131.010.0辛亏不是橙V519065.367918e+09二月四日丶无认证普通用户无层级无领域电子科技大学成都2017-06-091.044.0辛亏不是橙V463975.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-231.04.0辛亏不是橙V449425.581246e+09用户8282593879无认证普通用户无层级无领域无教育信息成都2016-03-23NaN4.0辛亏不是橙V
11.数据保存¶
In [111]:
#好了基础的用法就介绍到这里,再补充一点:数据的保存
#假设现在的data是已处理好的干净的数据,想要保存下来待下一步操作,DataFrame的方法to_csv把数据保存为csv文件:
#括号里可以指定保存路径,路径有相对路径和绝对路径之分
#比如说代码data.to_csv('data.csv')会在你目前的工作目录下直接创建一个data.csv的文件保存数据,这是相对路径
#再比如说代码data.to_csv('/Users/apple/Desktop/data.csv')直接指定数据保存的绝对路径“/Users/apple/Desktop/data.csv”(Mac系统,路径与Windows不大一样)
data.to_csv('/Users/apple/Desktop/data.csv')
如上所说,这是第一篇,探究pandas更加全面的一些基础用法。关于使用pandas进行数据清理、转换、字符串的操作、数据的分组聚合运算以及结合图形进行数据探索的内容会在下一篇《如何溜溜地使用pandas操作数据(二)》中涉及到,请持续关注。