老生常谈,从基础来看,我们仍然关心的是pandas对于外部数据是如何交互的。
还记得上节课的例子么?
提问:下列例子中,header = 4 , names = cnames 时,究竟能读到什么样的数据?
print(cnames)
irisdata = pd.read_csv("SIEP3_Iris.txt", header = None, name = cnames, encoding = "utf-8")
irisdata[::30]
希望了解全部参数的请移步API:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html
这里介绍一些常用参数:
对于存储着极为规整数据的Excel而言,其实是没必要一定要用Excel来存数据,尽管pandas也非常友好的提供了I/O接口。
irisdata.to_excel("SIPE3_irisdata.xls", index = None, encoding = "utf-8")
irisdata_from_excel = pd.read_excel("SIPE3_irisdata.xls", header = 0, encoding = "utf-8")
irisdata_from_excel[::30]
唯一重要的参数是:sheetname = k, 标志着一个Excel的第k个sheet页将会被取出。(默认从0开始)
JSON :网络传输中常用的一种数据格式。
仔细看一下,实际上这就是我们平时收集到异源数据的风格是一致的。
json_data = [
{"name":"Wang","sal":50000,"job":"VP"},
{"name":"Zhang","job":"Manager","report":"VP"},
{"name":"Li","sal":5000,"report":"Manager"}
]
data_employee = pd.read_json(json.dumps(json_data))
data_employee_ri = data_employee.reindex(columns = ["name","job","sal","report"])
print(data_employee_ri)
使用下列包,通过数据库配置建立Connection。
通过pandas.read_sql_query , read_sql_table , to_sql 进行数据库操作。
Python与数据库的交互方案有很多种,从数据分析师角度来看pandas方案比较合适,之后的讲义中会结合sql语法进行讲解。
进行MySQL数据库连接:
import pymysql
import pymysql.cursors
conn = pymysql.connect(
host = "127.0.0.1",
user = root,
password = "123456",
charset = "utf8",
cursorclass = pymysql.cursors.DictCursor
)
# pd.read_sql_query("sql",conn)
# df.to_sql("tablename",conn,flavor = "mysql")
在第一部分的基础上,数据会有更多的操纵方式:
横向拼接:直接DataFrame
pd.DataFrame([np.random.rand(2), np.random.rand(2), np.random.rand(2)],columns = ["c1", "c2"])
横向拼接:Concatenate
pd.concat([data_employee_ri, data_employee_ri, data_employee_ri])
纵向拼接:Merge
pd.merge(data_employee_ri, data_employee_ri, on = "name")
########
pd.merge(data_employee_ri, data_employee_ri, on = ["name","job"])
########
# 根据index关联,可以直接使用left_index或者right_index
data_emplyee_ri.index.name = "index1"
pd.merge(data_emplyee_ri,data_emplyee_ri,left_index = "index1", right_index = "index1")
TIPS:增加how关键字,并指定
DFA = pd.DataFrame(
{
"name":[u"老王",u"老张",u"老李"],
"sal":[5000,3000,1000]
}
)
print(DFA)
########
DFB = pd.DataFrame(
{
"name":[u"老王",u"老刘"],
"job":["VP","Manager"]
}
)
print(DFB)
########
# how = "left" :保留左表信息
pd.marge(DFA, DFB, on = "name", how = "left")
########
# how = "right" :保留右表信息
pd.marge(DFA, DFB, on = "name", how = "right")
########
# how = "inner" :保留两表交集信息,尽量避免出现缺失值
pd.marge(DFA, DFB, on = "name", how = "inner")
########
# how = "onter" :保留两表并集信息,优点最大程度的整合了已有信息,缺点会导致出现缺失值
pd.marge(DFA, DFB, on = "name", how = "onter")
接下来三个功能:map,applymap,apply功能,是绝大参数数据分析师在数据清洗这一步骤的必经之路。
他们分别的回答了以下问题:
不要再写什么for循环了!改变思维,提高编码和执行效率。
dataNumpy = np.asarray([
("Japan","Tokyo",4000),
("S.Korea","Seoul",1300),
("China","Beijing",9100)
])
DF = pd.DataFrame(dataNumpy,columns = ["nation","capital","GDP"])
print(DF)
def GDP_Factorize(v):
fv = np.float64(v)
if fv > 6000.0:
return "High"
elif fv < 2000.0:
return "Low"
else:
return "Medium"
DF["GDP_Level"] = DF["GDP"].map(GDP_Factorize)
DF["NATION"] = DF.nation.map(str.upper)
print(DF)
DF.applymap(lambda x:float(x)*2 if x.isdigit() else x.upper())
它会有点像我们后续介绍的agg,但是apply可以按行操作和按列操作,用axis控制即可。
DF.apply(lambda x:x["nation"] + x["capital"] + "_" + x["GDP"], axis = 1)
dataNumpy = np.asarray([
("Japan", "Tokyo", 4000)
("S.Korea", "Seoul", 1300)
("China", "Beijing", 9100)
])
DF = pd.DataFrame(dataNumpy, columns = ["nation", "capital", "GDP"])
print(DF)
########
DF.sort(["capotal", "nation"])
DF.sort("GDP", ascending = False)
DF.sort("GDP").sort(ascending = False)
DF.sort_index(axis = 1, ascending = True)
print(DF)
########
DF.rank()
DF.rank(ascending = False)
注意tied data(相同值)处理:
DF = pd.DataFrame(
{
"name":[u"老王",u"老刘",u"老李",u"老张"],
"sal":np.array([5000, 3000, 5000, 9000])
}
)
print(DF)
########
# DF.rank()默认使用method = "average",两条数据相等时,处理排名时大家都用平均值。
DF.sal.rank()
# method = "min",处理排名时大家都用最小值。
DF.sal.rank(method = "min")
# method = "max",处理排名时大家都用最大值。
DF.sal.rank(method = "max")
# method = "first",处理排名时谁先出现就先给谁较小的数值。
DF.sal.rank(method = "first")
DF = data_for_multi.unstack()
print(DF)
########
# 忽略缺失值
DF.mean(skipna = True)
DF.mean(skipna = False)
# 如果不想忽略缺失值,就要祭出fillna了。
DF.finllna(0).mean(axis = 1, skipna = False)
groupby的功能类似于SQL中的group by关键字
from IPython.display import Image
Image(filename = "SIP3_group.png")
# 分组的具体逻辑
irisdata_group = irisdata.groupby("class")
print(irisdata_group)
for level,subsetDF in irisdata_group:
print(level)
print(subsetDF)
分组可以快速实现MapReduce的逻辑 :
irisdata.groupby("class").agg(\
lambda x:((x - x.mean())**3).sum()*(len(x) - 0.0 )/\
(len(x) - 1.0)/(len(x) - 2.0)/(x.std() * np.sqrt((len(x) - 0.0)/(len(x) - 1.0)))**3 if len(x)>2 else None
)
irisdata.groupby("class").agg(spstat.skew)
在OLAP数据库上,为了避免groupby与join的二次操作,提出了sum()over(paritition by)的 开窗操作。
在pandas中,这波操作能够进一步呗transfrom锁取代:
pd.concat([irisdata, irisdata.groupby("class").transform("mean")], axis = 1)[::20]
一般来说,多列groupby的 一个副作用就是.groupby().agg()之后你的行index就已经变成了一个多列分组的分级索引。
如果我们希望达到Excel的数据透视表效果,行和列的索引自由交换,达到统计目的,究竟应该怎么做?
factor1 = np.random.randint(0, 3, 50)
factor2 = np.random.randint(0, 2, 50)
factor3 = np.random.randint(0, 3, 50)
hierindexDF = pd.DataFrame({"F1":factor1,"F2":factor2,"F3":factor3,"F4":values})
print(hierindexDF)
##########
hierindexDF_gbsum = hierindexDF.groupby(["F1","F2","F3"]).sum()
print(hierindexDF_gbsum)
# 观察 index 值
print(hierindexDF_gbsum.index)
# unstack:
# 无参数时,把最末端index置换到column上
# 有数字参数时,把指定位置的index置换到column上
# 有列表参数时,依次把特定位置的index置换到column上
hierindexDF_gbsum.unstack()
hierindexDF_gbsum.unstack(0)
hierindexDF_gbsum.unstack([2,0])
# 更进一步的,satck功能是和unstack所对应,把column上的多级索引换到index上去。
hierindexDF_gbsum.unstack([2,0]).stack([1,2])