Pandas十分钟入门到精通

入门Pandas

pandas是Python的一个用于数据分析的库:http://pandas.pydata.org
API速查:http://pandas.pydata.org/pandas-docs/stable/api.html
统计、分组、排序、透视表自由转换,如果你已经很熟悉结构化数据库与Excel的功能,就会知道pandas有过之而无不及。

上手玩Pandas

普通的程序员看到一份数据会怎么做?

  • 首先导入库准备处理
import datatime
import json
import codecs
import requests
import scipy as cp
import scipy.stats as spstat
import numpy as np
import pandas as pd
  • 使用requests下载iris数据集,进行数据演示。使用open方法将数据集下载到本地。
r = requests.get("http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data")
with codecs.open("SIEP3_Iris.txt","w","utf-8") as f:
	f.write(r.text)

使用open方法打开txt后读取前十行

with codecs.open("SIEP3_Iris.txt","r","utf-8") as f:
	lines = f.readlines()
for idx,line in enumerate(lines):
	print(line)
	if idx==10:
		break

  • 快速识别结构化数据,使用pandas可以快速查看数据集并且得到数据的行数以及列数的信息。
import pandas as pd
irisdata = pd.read_csv("SIEP3_Iris.txt",header = None,encoding = "utf-8")
print(irisdata)

  • 快速的操作元数据,将列名赋值到irisdata中
cnames = ["sepal_length","sepal_width","petal_length","petal_width","class"]
irisdata.columns = cnames
print(irisdata)

  • 快速过滤,将所有花瓣中达到最大值的取出。
petal_width_max = irisdata[irisdata["petal_width"]==irisdata.petal_width.max()]
print(petal_width_max)

  • 快速切片,按照行做抽样,取出三十分之一的数据,取出数据集的前两列。
print(irisdata.iloc[::30,:2])

  • 快速统计功能,value_counts()可以进行一个快速统计功能。
print(irisdata["class"].value_counts())
for x in range(4):
	g = irisdata.iloc[:x]
	print('{0:<12}'.format(g.name.upper()))
	print('Statistics: {0:>5} {1:>5} {2:>5} {3:>5}'.format(g.max(),g.min(),round(g.mean(),2),round(g.std(),2)))

  • 快速MapReduce功能,结合python的匿名函数,group_by功能,agg功能,可轻松实现MapReduce的逻辑
slogs = lambda x:sp.log(x)*x
entpy = lambda x:sp.exp((slogs(x.sum())-x.map(slogs).sum())/x.sum())
irisdata.groupby("class").agg(entpy)

欢迎来到Pandas的世界

Pandas的重要数据类型:

  • DataFrame(二维表)
  • Series(一维序列)
  • Index(行索引。行级元数据)

Series:pandas的长枪(数据表中的一列或一行,观测向量,一维数组。。。)

数据世界中对于任意一个个体的全面观测,或者对于任意一组个体某一属性的观测,全都可以抽象为Series的概念。
用值构建一个Series:
由默认的index和values组成。

Series = pd.Series(np.random.randn(4))
print(Series,tpye(Series))
print(Series.index)
print(Series.values)

Series支持过滤的原理就如同Numpy。

print(Series>0)
print(Series(Series>0))

当然也支持Broadcasting:

print(Series * 2)
print(Series + 5)

以及Universal Function:

print(np.exp(Series))
f_np = np.frompyfunc(lambda x:np(exp(x * 2 + 5), 1, 1))
print(f_np)

在序列上就使用行标,而不是创建一个二列的数据表,能够轻松辨别哪里是数据,哪里是元数据。

Series = pd.Series(Series.values,index=["norm_"unicode(i) for i in range(4)])
print(Series,type(Series))
print(Series.index,type(Series.index))
print(Series.values)

虽然行是有顺序的,但是仍然能够通过行级的index来访问到数据:

print(Series[["norm_2","norm_3"]])
print("norm_0" in Series)
print("norm_6" in Series)

默认行索引就像行号一样:

print(Series.index)

从Key不重复的Ordered Dict或者Dict来定义Series就不需要担心行索引重复:

Series_Dict = {
	"Japan":"Tokto",
	"S.Korea":"Seoul",
	"China":"Beijing"
}
Series_pdSeries = pd.Series(Series_Dict)
print(Series_pdSeries)
print(Series_pdSeries.value)
print(Series_pdSeries.index)

与Dict区别一: 有序

Series_IndexList = ["Japan","China","Singapore","S.Korea"]
Series_pdSeries = pd.Series(Series_Dict ,index = Series_IndexList)
print(Series_pdSeries)
print(Series_pdSeries.values)
print(Series_pdSeries.index)
print(Series_pdSeries.isnull())
print(Series_pdSeries.notnull())

与Dict区别二: index内值可以重复,尽管不推荐。

Series_IndexList = ["A","B","B","C"]
Series = pd.Series(Series.values,index = Serires_IndexList)
print(Series)
print(Series[["B","A"]])

整个序列级别元素数据信息:name
当数据序列以及index本身有了名字,就可以更方便的进行后续的数据关联啦!

print(Series_pdSeries.name)
print(Series_pdSeries.index.name)
################
Series_pdSeries.name = "Capital Series"
Series_pdSeries.index.name = "Nation"
print(Series_pdSeries.name)
print(Series_pdSeries.index.name)


DataFrame:pandas的战锤(数据表,二维数组)

Series的有序集合,就像R语言的DataFrame一样方便。仔细想想,绝大部分的数据形式都可以表示为DataFrame。


从Numpy二维数组,从文件或者从数据库定义:数据虽好,勿忘列名。

dataNumpy = np.array([
	('Japan',"Tokyo",4000),
	("S.Korea","Seoul",1300),
	("China","Beijing",9100)
])
DF1 = pd.DataFrame(dataNumpy,columns = ["nation","capital","GDP"])
print(DF1)

等长的列数据保存在一个字典(JSON)中,很不幸,字典是无序的。

dataDict = {
	"nation":['Tokyo',"Seoul","Beijing"],
	"GDP":["4900,1300,9100"],
	"capital":["Japan","S.Korea","Beijing"]
}
DF2 = pd.DataFrame(dataDict)
print(DF2)

从另一个DataFrame定义DataFrame:

DF2 = pd.DataFrame(DF2,columns=["nation","capital","GDP"])
print(DF2)

从DataFrame中取出列:两种方法(与JavaScript完全一致)

print(DF2.nation)
print(DF2.capital)
print(DF2["GDP"])

从DataFrame中取出行:两种方法

print(DF2[0:1]) # 给出的实际是DataFrame
print(DF2.ix[0]) # 通过对应的Index给出行

像Numpy切片一样的终极招式:iloc

print(DF2.iloc[0,:])
print(DF2.iloc[:,0])

听说你从Alter Table地狱来?pandas笑了。

然而动态的增加列无法用“.”的方式完成,只能用“[ ]”

DF2["population"] = [1600,130,55]
DF2["region"] = "East_Asian"
print(DF2)

Index:pandas进行数据操作的鬼牌(行级索引)

行级索引是

  • 元数据
  • 可能由真实数据产生,因此可以视作数据
  • 可以由多重索引可就是多个列组合而成
  • 可以和列名进行交换,也可以进行堆叠和展开,达到Excel透视表功能。

Index有很多种写法,一些重要的索引类型包括:

  • pd.index(普通)
  • Int64Index(数值型索引)
  • MultiIndex(多重索引,在数据操纵中更详细描述)
  • DatatimeIndex(以时间格式作为索引)
  • PeriodIndex(含周期的时间格式作为索引)

直接定义普通索引,长得就和普通的Series一样:

index_names = ["a","b","c"]
Series_for_index = pd.Series(index_names)
print(pd.Index(index_names))
print(pd.Index(Series_for_index))

可惜。。。Immutable,牢记!

index_names = ["a","b","c"]
index = pd.Index(index_names)
print(index.get_values())
# index[2] = "d"  # 不能这样写
# 扔进去一个含有多元组的List,就有了Immutable

可惜,如果这个List Comperhension改成小括号的话,就不对了。

multi = pd.Index([("Row_"+str(x+1),"Col_"+srt(y+1)) for x in range(4) for y in range(4)])
multi.name = ["index1","index2"]
print(multi)

对于Series来说,如果拥有了多层Index,数据,变形!
下列代码说明

  • 二重MultiIndex的Series可以unstack()或者DataFrame。
  • DataFrame可以stack成拥有二重MultiIndex的Series。
data_for_multi = pd.Series(range(16),index=multi)
print(data_for_multi)
print(data_for_multi.unstack())
print(data_for_multi.unstack().stack())

我们来看一下非平衡数据的样子:
Row_1,2,3,4和Col_1,2,3,4并不是全组合的。

multi = pd.Index([("Row_"+str(x),"Col_"+str(y)) for x in range(5),for y in range(5)])
print(multi)
data_for_multi = pd.Series(np.arange(10),index = multi)
print(data_for_multi)
print(data_for_multi.unstack())
print(data_for_multi.unstack().stack())

Datetime标准库如此好用,你值得拥有。

dates = [datetime.datetime(2020,1,1),datetime.datetime(2020,3,1),datetime.datetime(2020,3,26)]
pd.DatetimeIndex(dates)

如果你不仅需要时间格式统一,时间频率也想统一的话:

periodindex = pd.period_range("2020-01","2020-03",freq="M")
print(periodindex)

月级精度和日级精度如何转换?asfreq方可办到。

print(periodindex.asfreq("D",how="start"))
print(periodindex.asfreq("D",how="end"))

如何真正的把两种频率的时间精度匹配上?

periodindex_mon = pd.period_range("2020-01","2020-03",freq="M").asfreq("D",how="start")
periodindex_day = pd.period_range("2020-01-01","2020-03-26",freq="D")
print(periodindex_mon)
print(periodindex_day)

粗糙度数据 + reIndex + ffill/bfill

full_ts1 = pd.Series(periodindex_mon,index = periodindex_mon).reindex(periodindex_day)
print(full_ts1)
full_ts2 = pd.Series(periodindex_mon,index = periodindex_mon).reindex(periodindex_day,method="ffill")
print(full_ts2)
full_ts3 = pd.Series(periodindex_mon,index = periodindex_mon).reindex(periodindex_day,method="bfill")
print(full_ts2)

关于索引,方便的操作有哪些?

前面已经描述过了,索引有序、重复,但一定程度上也能通过key来访问,也就是说,某些集合操作都是可以支持的。

index1 = pd.Index(["A","B","B","C","C"])
index2 = pd.Index(["C","D","E","E","F"])
index3 = pd.Index(["B","C","A"])
print(index1.append(index2))
print(index1.difference(index2))
print(index1.intersection(index2))
print(index1.union(index2))
print(index1.isin(index2))
print(index1.delete(2))
print(index1.drop("A"))
print(index1.insert(0,"K"))
print(index1.is_monotonic,index2.is_monotonic,index3.is_monotonic)
print(index1.is_unique,index2.is_unique,index3.is_unique)

发布了13 篇原创文章 · 获赞 25 · 访问量 1497

猜你喜欢

转载自blog.csdn.net/qq_45414559/article/details/105108496