如何溜溜地使用pandas操作数据(一)

如何溜溜地使用pandas操作数据(一)

注:本文版权由Alfred所有,首发于微信公众号「DataCastle数据城堡」(ID:DataCastle2016),如需转载还请提前联络[email protected],非常感谢。


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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771
In [47]:
#使用tail()返回末尾的数据
data.tail(3)
Out[47]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量
54922 6122405911 别把过去抱得太紧了 无认证 普通用户 无层级 无领域 电子科技大学 海淀区 2/22/17 - 8
54923 6135533202 小名竹子小姐 无认证 普通用户 无层级 无领域 电子科技大学 株洲 1900/1/0 - -
54924 6174296618 一件借来的马甲 无认证 普通用户 无层级 无领域 无教育信息 未知 4/24/17 - 667
In [48]:
#有时候由于数据太多,我们不能确定知道了数据的首尾就可以掌握数据的大致情况,
#可以使用sample()来随机抽取出数据中的指定条数,如下随机抽取了5条数据
data.sample(5)
Out[48]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量
24331 3931940541 走向尽头_19021 无认证 普通用户 无层级 无领域 无教育信息 成都 1900/1/0 - 115
39762 5602246379 泰陵玑衡 无认证 普通用户 无层级 无领域 电子科技大学 西安 1900/1/0 - NaN
4013 1796225561 二大神 无认证 普通用户 无层级 无领域 郑州大学 郑州 6/12/17 16 156
15373 5736564432 to挑衅本尊 无认证 普通用户 无层级 无领域 电子科技大学 巴中 5/15/17 1 27
28661 5688941824 时间肯定好 无认证 普通用户 无层级 无领域 电子科技大学 成都 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]:

UID
count 5.492500e+04
mean 3.744216e+09
std 1.540637e+09
min 1.048020e+05
25% 2.395101e+09
50% 3.303743e+09
75% 5.384490e+09
max 6.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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量
666 3044329831 左道幽氳 无认证 普通用户 无层级 无领域 无教育信息 成都 6/13/17 108 80
667 5792376745 我叫小笑子 无认证 普通用户 无层级 无领域 电子科技大学 未知 6/11/17 108 63
668 5172765695 易二八 无认证 普通用户 无层级 无领域 无教育信息 成都 6/13/17 108 32
In [55]:
#想要获取666,777,888的记录,使用:
data.loc[[666,777,888]]
Out[55]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量
666 3044329831 左道幽氳 无认证 普通用户 无层级 无领域 无教育信息 成都 6/13/17 108 80
777 1313468125 吖呀飞扬 无认证 普通用户 无层级 无领域 西北农林科技大学 成都 6/13/17 93 110
888 2026953081 Mr_北极bear 无认证 普通用户 无层级 无领域 电子科技大学 长春 6/13/17 81 534
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 幸福女人有心计 微博情感帐号
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 一件借来的马甲 无认证

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 幸福女人有心计 微博情感帐号
9 mickey-fang 深圳淘商网络科技有限公司人力资源总监
10 电影攻略菌 三只狐狸影评人
In [59]:
#获取前5行,第9-11列的数据
data.iloc[:5,8:]
#注意loc和iloc的区别
Out[59]:

最近发博时间 发博量 粉丝量
0 6/13/17 5663 24642
1 6/13/17 4727 445183
2 6/13/17 4608 2822
3 6/13/17 4480 1762
4 6/13/17 3781 1771

4.更多行列操作

In [60]:
#在数据表中新增一列“test”,赋值为NaN(缺失值)
#首先把numpy导入进来,因为要用到numpy的缺失值nan
import numpy as np
data['test'] = np.nan

#好了,看一下现在的数据长什么样子,可以看到最右边已成功添加一列“test”,值为NaN
data.head()
Out[60]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 test
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 NaN
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 NaN
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 NaN
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 NaN
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 NaN
In [61]:
#把“test”列重新赋值为999
data['test'] = 999
#瞅一眼数据
data.head()
Out[61]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 test
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 999
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 999
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 999
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 999
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 999
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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 test
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 True
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 True
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 False
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 True
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 True
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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 test
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 辛亏不是橙V
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 这丫竟是橙V,大家快来孤立他!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 这丫竟是橙V,大家快来孤立他!
In [64]:
#于是,由上面的方法可以引出,如果要想给数据特定的位置赋值,比如想要把‘test’列的2-4行赋值为“我不听我不听!”,可以这样:
data.loc[2:4,'test'] = '我不听我不听!'
data.head()
Out[64]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 test
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 我不听我不听!
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
In [65]:
#如果想要更改某列的列名,怎么做呢?
data.rename(columns={'test':'乱加的一列'}, inplace = True)
#使用rename,指定columns,使用字典mapping(映射)的方法改变,记得加上inplace=True,表示直接在数据表data上固化这个操作
data.head()
Out[65]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 我不听我不听!
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
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 列12
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 我不听我不听!
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
5 5330513605 张宸hgh 杭州慎思行广告策划有限公司广告企划 橙V C3 无领域 无教育信息 未知 6/13/17 3763 1911 这丫竟是橙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 列11
0 1363172732 小仙女tracy遇见幸福 橙V 这丫竟是橙V,大家快来孤立他! 百胜咨询(上海)有限公司采购专员 C5 美食 徐汇区 同济大学 6/13/17 5663 24642
1 2571350940 彩票老聂 橙V 这丫竟是橙V,大家快来孤立他! 微电商达人 C2 电商 成都 四川师范大学 6/13/17 4727 445183
2 6067613738 淘折扣-帮帮VIP 普通用户 我不听我不听! 无认证 C3 无领域 南充 电子科技大学 6/13/17 4608 2822
3 5330304545 教你品味穿衣 橙V 我不听我不听! 司瓦特(杭州)能源科技有限公司经理 C3 无领域 未知 无教育信息 6/13/17 4480 1762
4 5330304450 张戎强_15565 橙V 我不听我不听! 深圳市事必成电子有限公司财务 C3 无领域 未知 无教育信息 6/13/17 3781 1771
5 5330513605 张宸hgh 橙V 这丫竟是橙V,大家快来孤立他! 杭州慎思行广告策划有限公司广告企划 C3 无领域 未知 无教育信息 6/13/17 3763 1911
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 列12
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
5 5330513605 张宸hgh 杭州慎思行广告策划有限公司广告企划 橙V C3 无领域 无教育信息 未知 6/13/17 3763 1911 这丫竟是橙V,大家快来孤立他!
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 6067613738 淘折扣-帮帮VIP 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 我不听我不听!

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 列12
0 1363172732 小仙女tracy遇见幸福 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 2571350940 彩票老聂 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
3 5330304545 教你品味穿衣 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 5330304450 张戎强_15565 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
In [70]:
#同样,想要删除特定列,可以使用:
data_test.drop(['列1','列2'], axis = 1)
#axis=0表示行所在的轴,axis=1表示列所在的轴
Out[70]:

列3 列4 列5 列6 列7 列8 列9 列10 列11 列12
0 百胜咨询(上海)有限公司采购专员 橙V C5 美食 同济大学 徐汇区 6/13/17 5663 24642 这丫竟是橙V,大家快来孤立他!
1 微电商达人 橙V C2 电商 四川师范大学 成都 6/13/17 4727 445183 这丫竟是橙V,大家快来孤立他!
2 无认证 普通用户 C3 无领域 电子科技大学 南充 6/13/17 4608 2822 我不听我不听!
3 司瓦特(杭州)能源科技有限公司经理 橙V C3 无领域 无教育信息 未知 6/13/17 4480 1762 我不听我不听!
4 深圳市事必成电子有限公司财务 橙V C3 无领域 无教育信息 未知 6/13/17 3781 1771 我不听我不听!
5 杭州慎思行广告策划有限公司广告企划 橙V C3 无领域 无教育信息 未知 6/13/17 3763 1911 这丫竟是橙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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
7 2912165441 上海吃喝玩乐嗨 天娱文化传媒有限公司歌手 橙V C3 美食 无教育信息 未知 2017-06-13 3500 1855222.0 这丫竟是橙V,大家快来孤立他!
8 2203959564 幸福女人有心计 微博情感帐号 橙V C1 情感两性 中国科学院大学 广州 2017-06-13 2947 2048157.0 这丫竟是橙V,大家快来孤立他!
10 3947532062 电影攻略菌 三只狐狸影评人 橙V C1 电影 常熟理工学院 台北市 2017-06-13 2887 8263459.0 这丫竟是橙V,大家快来孤立他!
11 2484832905 精选星座微博 知名星座命理博主 橙V C1 星座命理 无教育信息 未知 2017-06-13 2720 10068055.0 这丫竟是橙V,大家快来孤立他!
12 1921208427 超搞笑集中营 知名搞笑幽默博主 橙V C1 搞笑幽默 无教育信息 未知 2017-06-13 2645 17380052.0 这丫竟是橙V,大家快来孤立他!
In [81]:
#选取粉丝量在1000000到1200000之间的数据
data[(data['粉丝量']>1000000) & (data['粉丝量']<1200000)]
#这里可以看到,有些微博发博量那么小竟然有那么多的粉丝,这让我开始质疑这里的发博量是怎么统计的,以及数据真实性,这个原因值得我们探寻。当然这是外话,暂且按下不表。
Out[81]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
60 1974945511 Marco_徐晓峰 上海览领资产管理有限公司董事长兼总裁 橙V C1 财经 无教育信息 浦东新区 2017-06-13 989 1030818.0 这丫竟是橙V,大家快来孤立他!
278 1996808583 中国移动广西公司 中国移动通信集团广西有限公司 蓝V 无层级 无领域 无教育信息 未知 2017-06-13 245 1045645.0 辛亏不是橙V
940 2219368761 搜狐视频移动客户端 搜狐视频移动客户端官方微博 蓝V C2 综艺节目 无教育信息 未知 2017-06-13 77 1166605.0 辛亏不是橙V
1213 2802767157 睿皓客服 广州市睿皓投资管理有限公司 蓝V 无层级 无领域 无教育信息 未知 2017-06-10 60 1112197.0 辛亏不是橙V
16698 3504492202 财经新闻观察员yojo 鼎盟资产管理有限公司 项目经理 橙V C5 无领域 无教育信息 东城区 2017-04-27 0 1003491.0 这丫竟是橙V,大家快来孤立他!
16737 3296184181 创意设计师--Lucy 鸿展广告印务有限公司 平面设计 橙V C5 设计美学 无教育信息 徐汇区 2017-04-27 0 1002837.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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
59 2155487004 热门奇事趣闻 无认证 普通用户 C1 搞笑幽默 无教育信息 广州 2017-06-13 1008 2478912.0 辛亏不是橙V
326 2092488475 萌死你不负责 无认证 普通用户 C1 动物宠物 无教育信息 未知 2017-06-13 214 4077139.0 辛亏不是橙V
8074 2822792812 小女子爱靓妆 无认证 普通用户 C5 时尚 逢甲大學 石家庄 2017-06-06 6 2047280.0 辛亏不是橙V
8075 2822792812 小女子爱靓妆 无认证 普通用户 C5 时尚 解放军艺术学院 石家庄 2017-06-06 6 2047280.0 辛亏不是橙V
10088 1650434880 热门百科搜罗 无认证 普通用户 C4 科学科普 无教育信息 朝阳区 2017-06-13 4 5413067.0 辛亏不是橙V
26207 2912473701 奥舒小铺 无认证 普通用户 C5 美妆 无教育信息 海淀区 2016-09-23 0 3038936.0 辛亏不是橙V
39187 3089575472 爱美女人宝典 无认证 普通用户 C4 美妆 无教育信息 南京 2017-06-01 3 11089043.0 辛亏不是橙V
44083 2092275377 IT科技全知道 无认证 普通用户 C5 数码 无教育信息 佛山 2016-12-21 0 1619559.0 辛亏不是橙V
In [83]:
#再在前面的基础上添上一个条件:层级不是“C5”的
data[(data['粉丝量']>1000000) & (data['v区分'] == '普通用户') & (data['层级'] != 'C5')]
Out[83]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
59 2155487004 热门奇事趣闻 无认证 普通用户 C1 搞笑幽默 无教育信息 广州 2017-06-13 1008 2478912.0 辛亏不是橙V
326 2092488475 萌死你不负责 无认证 普通用户 C1 动物宠物 无教育信息 未知 2017-06-13 214 4077139.0 辛亏不是橙V
10088 1650434880 热门百科搜罗 无认证 普通用户 C4 科学科普 无教育信息 朝阳区 2017-06-13 4 5413067.0 辛亏不是橙V
39187 3089575472 爱美女人宝典 无认证 普通用户 C4 美妆 无教育信息 南京 2017-06-01 3 11089043.0 辛亏不是橙V

8.数据排序

In [84]:
#观察数据发现,数据应该是按照发博量降序的,假如我想按照“粉丝量”排序,可以使用sort_values(),把想要排序的列传值给by:
#注意,这里为了更好显示还是使用了head()
data.sort_values(by='粉丝量').head()
Out[84]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
39386 5801712160 Z崔廷松TI 无认证 普通用户 无层级 无领域 电子科技大学 临沂 2016-03-14 0 0.0 辛亏不是橙V
28633 5580676423 csm小玉_625 无认证 普通用户 无层级 无领域 电子科技大学 未知 NaT 0 0.0 辛亏不是橙V
28631 5576825313 就是何小猪_58282 无认证 普通用户 无层级 无领域 电子科技大学 成都 NaT 0 0.0 辛亏不是橙V
19740 5241977690 MISS韓小艾L 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-06 0 0.0 辛亏不是橙V
46983 5787419079 取名字都被取完了 无认证 普通用户 无层级 无领域 电子科技大学 金华 NaT 0 0.0 辛亏不是橙V
In [87]:
#哎呀妈呀,默认的是升序排列,我想要的是按照“粉丝量”降序排列,所以需要加上ascending=False
#选取数据表中粉丝量最多的前5个微博
data.sort_values(by='粉丝量',ascending=False).head()
Out[87]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
39 1663072851 中国日报 中国日报官方微博 蓝V C1 媒体 无教育信息 未知 2017-06-13 1478 27477245.0 辛亏不是橙V
12 1921208427 超搞笑集中营 知名搞笑幽默博主 橙V C1 搞笑幽默 无教育信息 未知 2017-06-13 2645 17380052.0 这丫竟是橙V,大家快来孤立他!
94 2316673484 每日幽默趣事 知名搞笑幽默博主 橙V C1 搞笑幽默 无教育信息 东城区 2017-06-13 681 12263190.0 这丫竟是橙V,大家快来孤立他!
8305 3090413830 时尚生活女郎网 时尚生活女郎网官方微博 蓝V 无层级 无领域 清华大学 黄浦区 2017-06-05 5 11582338.0 辛亏不是橙V
39187 3089575472 爱美女人宝典 无认证 普通用户 C4 美妆 无教育信息 南京 2017-06-01 3 11089043.0 辛亏不是橙V
In [88]:
#假如我想要首先按照“最近发博时间”降序排序,“最近发博时间”相同的情况下再按照“粉丝量”降序排序,应该怎么做?
#此时只需要传给by一个列表就好啦
data.sort_values(by=['最近发博时间','粉丝量'],ascending=False).head()
Out[88]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
39 1663072851 中国日报 中国日报官方微博 蓝V C1 媒体 无教育信息 未知 2017-06-13 1478 27477245.0 辛亏不是橙V
12 1921208427 超搞笑集中营 知名搞笑幽默博主 橙V C1 搞笑幽默 无教育信息 未知 2017-06-13 2645 17380052.0 这丫竟是橙V,大家快来孤立他!
94 2316673484 每日幽默趣事 知名搞笑幽默博主 橙V C1 搞笑幽默 无教育信息 东城区 2017-06-13 681 12263190.0 这丫竟是橙V,大家快来孤立他!
11 2484832905 精选星座微博 知名星座命理博主 橙V C1 星座命理 无教育信息 未知 2017-06-13 2720 10068055.0 这丫竟是橙V,大家快来孤立他!
10 3947532062 电影攻略菌 三只狐狸影评人 橙V C1 电影 常熟理工学院 台北市 2017-06-13 2887 8263459.0 这丫竟是橙V,大家快来孤立他!
In [89]:
#另外需要注意的是在排序时,缺失值会被默认放在最后,看看这个按照“粉丝量”降序排序的数据末尾都是粉丝量为NaN的
data.sort_values(by='粉丝量',ascending=False).tail()
Out[89]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
54767 5255416206 用户5255416206 无认证 普通用户 无层级 无领域 无教育信息 未知 2015-01-04 0 NaN 辛亏不是橙V
54820 5554815685 时光暖心掘用 无认证 普通用户 无层级 无领域 电子科技大学 未知 NaT 0 NaN 辛亏不是橙V
54860 5754177219 NaN 无认证 普通用户 无层级 无领域 无教育信息 NaN NaT 0 NaN 辛亏不是橙V
54874 5809538378 夏商丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-08 5 NaN 辛亏不是橙V
54883 5848764247 郭局辰郭 无认证 普通用户 无层级 无领域 电子科技大学 百色 NaT 0 NaN 辛亏不是橙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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-04-11 NaN 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 无层级 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 NaN 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 NaN 4.0 辛亏不是橙V
44942 NaN NaN NaN NaN NaN NaN NaN NaN NaT NaN NaN NaN
In [100]:
#丢弃所有包含缺失数据的行(只要一行中包含一个缺失数据,即丢弃):
data_test.dropna()
Out[100]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 无层级 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-04-11 NaN 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 无层级 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 NaN 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 NaN 4.0 辛亏不是橙V
In [102]:
#丢弃包含缺失数据的列(这个方法不常用到,了解一下就好)
data_test.dropna(axis = 1)
#可以发现包含NaN的“发博量”一列被删除了
Out[102]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-04-11 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 无层级 无领域 无教育信息 未知 2017-06-09 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 4.0 辛亏不是橙V
In [104]:
#如果决定处理缺失数据的方式不是直接丢弃,而是填充数据
#为了更好地说明操作方法,再构造一下数据集
data_test.loc[44942]=np.nan
data_test.loc[[49334,14818],'层级'] = np.nan
#瞅一眼数据长什么样子
data_test
Out[104]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 NaN 无领域 电子科技大学 成都 2017-04-11 NaN 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 NaN 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 NaN 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 NaN 4.0 辛亏不是橙V
44942 NaN NaN NaN NaN NaN NaN NaN NaN NaT NaN NaN NaN
In [105]:
#好,接下来就可以进行填充缺失数据的操作了:填充数据使用的是fillna()方法,括号里传入填充的方法
#假如我想要把所有的缺失数据都填充为0,则在括号里直接传入0:
#可以看到所有的缺失数据都被成功填充为0(可能这里你就要怼我了:明明最后一行的最近发博时间没有被填充为0啊,其实,计算机默认的时间起点就是“1970-01-01”)
data_test.fillna(0)
Out[105]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 0 无领域 电子科技大学 成都 2017-04-11 0.0 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 0 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 0.0 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 0.0 4.0 辛亏不是橙V
44942 0.000000e+00 0 0 0 0 0 0 0 1970-01-01 0.0 0.0 0
In [106]:
#假如我想要给每一列的缺失数据填充不一样的值,比如说给“层级”列填充“C0”,给“发博量”填充“999”,则传入一个字典mapping(映射)
data_test.fillna({'层级':'C0','发博量':'999'})
Out[106]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 C0 无领域 电子科技大学 成都 2017-04-11 999 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 C0 无领域 无教育信息 未知 2017-06-09 1 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 999 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 999 4.0 辛亏不是橙V
44942 NaN NaN NaN NaN C0 NaN NaN NaN NaT 999 NaN NaN
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区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 NaN 无领域 电子科技大学 成都 2017-04-11 NaN 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 NaN 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 1.0 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 1.0 4.0 辛亏不是橙V
44942 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 1.0 4.0 辛亏不是橙V
In [110]:
#这种填充方法有一个bug,就是万一数据连着10行都是缺失数据的话,那么使用ffill的方法填充的话这10行缺失数据都会被填充成上面一行有实值的数据,这样的填充方法很不准确,比如说如果是时间序列数据的话,前一天和后一天的数据可能是有强相关的,可是有时相隔10天的数据差别是很大的。
#为此,有一个限定最大连续填充行数的方法limit,假如我想要限定往下填充只允许填充一行,则:
data_test.fillna(method='ffill',limit=1)
#可以发现,这种填充方法的话,44942行的“发博量”值就没有被连续填充
Out[110]:

UID 昵称 认证信息 v区分 层级 领域 教育信息 城市 最近发博时间 发博量 粉丝量 乱加的一列
49334 3.501844e+09 随遇而安SYG 无认证 普通用户 NaN 无领域 电子科技大学 成都 2017-04-11 NaN 59.0 辛亏不是橙V
14818 5.574223e+09 今天天气不错挖 无认证 普通用户 NaN 无领域 无教育信息 未知 2017-06-09 1.0 51.0 辛亏不是橙V
16033 1.598527e+09 pi21 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-03 1.0 131.0 辛亏不是橙V
21157 2.836428e+09 修身520 无认证 普通用户 无层级 无领域 大竹二中 福州 2016-11-13 1.0 10.0 辛亏不是橙V
51906 5.367918e+09 二月四日丶 无认证 普通用户 无层级 无领域 电子科技大学 成都 2017-06-09 1.0 44.0 辛亏不是橙V
46397 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 1.0 4.0 辛亏不是橙V
44942 5.581246e+09 用户8282593879 无认证 普通用户 无层级 无领域 无教育信息 成都 2016-03-23 NaN 4.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操作数据(二)》中涉及到,请持续关注。

猜你喜欢

转载自blog.csdn.net/DataCastle/article/details/77749291