yebaoer

数据统计与分析-Pandas

1. 读写不同数据源的数据

1.1 读写(txt/csv)

import pandas as pd

# 读取文本数据
data_txt = pd.read_csv(\'../data/meal_order_info.txt\', sep=\' \')
data_csv = pd.read_csv(\'../data/meal_order_info.csv\', encoding=\'GBK\', header=0)  # 如果数据没有标题可以设置标题采用names属性

# 将数据框存储为文本文件数据
data_csv.to_csv(\'tmp/data_csv.csv\', index=None, encoding=\'gbk\')

1.2 读写(excel)

# 读取Excel文件
data_excel = pd.read_excel(\'data/meal_order_detail.xlsx\', sheet_name=\'meal_order_detail2\')
data_excel.to_excel(\'tmp/data_excel.xlsx\', index=None, sheet_name=\'test1\')

1.3 注意事项

# header=0 是将第一列当作列名(有列名时可默认不写)
# header=None 读进来的列名就是系统默认的0,1,2... 序列号(没有标题的时候)

# csv文件有列标题,但是想自己换成别的列标题
df_example = pd.read_csv(\'Pandas_example_read.csv\') df_example.columns = [\'A\',\'B\',\'C\']

# 在读数的同时自定义标题
df_example = pd.read_csv(\'Pandas_example_read.csv\', names=[\'A\', \'B\',\'C\'])

2. DataFrame的常用操作

2.1 Series (只有一列)

# Series组成部分:pd.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
"""series 的创建方式"""
lst = [1,3,5,6,10,23]
s = pd.Series(lst)    # 可以通过index指定索引,如果不指定索引,则会自动从0开始生成索引,我们叫做隐式索引
s = pd.Series(lst,index=["A","B","C","D","E","F"])                   # 通过index设置显式索引
s = pd.Series(np.random.randint(1,10,size=(3,)),index=[\'a\',\'b\',\'c\']) # 通过numpy创建
dic = {"A":1,"B":2,"C":3,"D":2}
s2 = pd.Series(dic)            # 通过字典创建

"""Series的索引和切片"""
# Series隐式索引的操作(索引是默认从0开始的数字)   iloc对隐式索引进行操作,左闭右开
lst = [1,3,5,6,10,23]
s = pd.Series(lst)
# s[0]  s[[0,1]]==s[0:2]==s.iloc[0:2]==s.iloc[[0,1]]   

"""Series显式索引的操作"""   自定义索引       loc对显式索引进行操作,两端都可取
lst = [1,3,5,6,10,23]
s1 = pd.Series(lst,index=["A","B","C","D","E","F"])
# s1["A"]  s1[["A","B"]]==s1["A":"B"]==s1.loc["A":"B"]==s1.loc[["A","B"]]

"""显示Series部分数据内容"""
# s.head(n) 该函数代表的意思是显示前多少行,可以指定显示的行数,不写n默认是前5行
# s.tail(n) 该函数代表的意思是显示后多少行,可以指定显示的行数,不写n默认是前5行

dic = {"A":1,"B":2,"C":3,"D":2}
s2 = pd.Series(dic)
s2.unique()                # 原s2并未修改,该结果返回的是一维数组  array([1, 2, 3], dtype=int64)

"""Series的相加运算"""
# Series相加,会根据索引进行操作,索引相同则数值相加,索引不同则返回NaN
# NaN在pandas解释中为 not a number ,它是float类型,表示缺失数据,可以参与运算。
lst = [1,3,5,6,10,23]
s1 = pd.Series(lst,index=["A","B","C","D","E","F"])
# s2
dic = {"A":1,"B":2,"C":3,"D":2}
s2 = pd.Series(dic)
s3 = s2+s1
s3

"""Series缺失值操作"""
# s.notnull() 不为空返回True,为空返回False
# s.isnull() 不为空返回False,为空返回True
s3.isnull()        # s3.notnull()

# 只显示不为空的行
s3[s3.notnull()]
# 只显示为空的行
s3[s3.isnull()]

2.2 DataFrame(一张表)

"""创建dataframe"""
# 通过列表创建
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
print(d)
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)

# 通过字典创建
d={\'color\':[\'blue\',\'green\',\'yellow\',\'red\',\'white\'],
   \'object\':[\'ball\',\'pen\',\'pencil\',\'paper\',\'mug\'],
   \'price\':[1.2,1.0,0.6,0.9,1.7]}
frame = pd.DataFrame(d,index=[\'a\',\'b\',\'c\',\'d\',\'e\'])
print(frame)

# 通过numpy创建
pd.DataFrame(np.random.randint(0, 10, (2, 3)), index=["A", "B"], columns=[0, 1, 2])

"""dataframe的常用属性"""
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df.values)        # 返回一个二维数组,一行就是一个一维数组, 可按所以取值( df.values[0]取第一行数据 )
print(df.index)
print(df.columns)
print(df.shape)
print(df.dtypes)

"""dataframe的查改增删操作"""
# 访问数据框中的元素
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)

# print(df[\'A\'])         # 单列数据访问
# print(df[[\'A\', \'C\']])  # 多列数据访问

# print(df.head(3))     # 访问某几行数据
# print(df.tail(3))

# print(df.iloc[0, 0])    # 按照行列顺序进行数据访问
# print(df.iloc[0:3, 0])
# print(df.iloc[:, 0])
# print(df.iloc[0, :])
# print(df.iloc[1:3, 1:3])

# print(df.loc[\'a\', \'A\'])   # 按照行列名称进行数据访问
# print(df.loc[\'a\':\'c\', \'A\'])
# print(df.loc[:, \'A\'])
# print(df.loc[\'a\', :])
# print(df.loc[[\'b\',\'c\'], [\'B\', \'C\']])

# 注意如下方式返回值的区别
print(df.iloc[:, 0])          # <class \'pandas.core.series.Series\'>
print(df.iloc[:, 0:1])        # <class \'pandas.core.frame.DataFrame\'>  两个冒号取出来的是一个dataframe


# 修改数据框中的元素
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)
df.loc[\'a\', \'A\'] = 101
df.loc[:, \'B\'] = 0.25
df.loc[:, \'C\'] = [1, 2, 3, 4]
print(df)


# 为数据框增添数据
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)
df[\'E\'] = 5                     # 第E列的所有行都为 5
df[\'F\'] = [1, 2, 3, 4]          # 第F列的行一次为 [1, 2, 3, 4]
print(df)


# 删除数据框中的元素
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)
print(df.drop(\'D\', axis=1, inplace=False))   # 删除数据框的列元素 inplace=False 不改变原来dataframe
print(df.drop([\'a\', \'c\'], axis=0))           # 输出数据框的行元素    

3. 描述分析dataframe数据

import numpy as np
d=[[1.3,2.0,3,4],[2,4,1,4],[2,5,1.9,7],[3,1,0,11]]
df = pd.DataFrame(d, index=[\'a\', \'b\', \'c\', \'d\'], columns=[\'A\', \'B\', \'C\', \'D\'])
print(df)
print(np.mean(df, axis=1))      # dataframe中对每一列进行求一个均值
print("+++")
# df.mean(axis=1)               # dataframe中对每一 列 进行求一个均值
# df.std()                      # dataframe中对每一 行 进行求一个标准差
# df.describe()                 # 对整个表格进行一个描述包含(count,mean,std,min,25%,50%,75%,max)默认按列计算
df[\'A\'].value_counts()          # 对A这列进行一个词频统计

4. 转换与处理时间序列数据

时间模块相关的类

import pandas as pd

order = pd.read_csv(\'../data/meal_order_info.csv\', encoding=\'gbk\')
# print(order)

# 通过pd.to_datetime将数据改成
print(order[\'lock_time\'].dtypes)                        # object  字符串
order[\'lock_time\'] = pd.to_datetime(order[\'lock_time\']) # datetime64[ns]   时间格式
print(order[\'lock_time\'].dtypes)
print(pd.DatetimeIndex(order[\'lock_time\']))          # 用来指代一系列事件点的数据结构 
print(pd.PeriodIndex(order[\'lock_time\'], freq=\'H\'))  # freq=\'H\',以小时(可以改成D...)为时间间隔的,指代一段时间
order[\'lock_time\'][0]              # Timestamp(\'2016-08-01 11:11:46\')

# 获取时间信息
print(order[\'lock_time\'][0].year)      # 获取数据年份信息 2016
print(order[\'lock_time\'].dt.year)      # 获取数据年份信息 这种方法的速度快一些
print(order[\'lock_time\'].dt.month)     # 获取数据月份信息
print(order[\'lock_time\'].dt.week)      # 获取数据周次信息

# 修改时间信息
print(order[\'lock_time\'] + pd.Timedelta(days=1))       # 时间平移,整行加一个时间
print(order[\'lock_time\'][1] - order[\'lock_time\'][0])   # 求时间差别  0 days 00:20:09   (也可以用一列来减去一行数据)

注意: 将时间形式的字符串改成时间数据可以用(to_datetime,DatetimeIndex,PeriodIndex(需要设置时间间隔))。获取时间时优先采用order[\'lock_time\'].dt.year来获取整行数据的年份,速度会优于order[\'lock_time\'][i].year循环。 修改时间采用pd.Timedelta这个类设置,之间相加改变一整列的时间。计算时间查可以行于行之间相减,也可行减去一个具体时间。

5. 分组聚合进行组内计算

  • 分组 group
  • 聚合 agg
import pandas as pd

df = pd.read_csv("../data/groupby.csv")

# 计算各城市学生的评价成绩(先按城市分组,再对分组之后的成绩求平均值)
# 一列的时候是series,重置索引变成dataframe
# result = df.groupby(\'address\')[\'score\'].mean().reset_index()
# print(result, type(result))

# 求各城市的学生数量
# result = df.groupby(\'address\').count().reset_index()    # 得到的是全部属性的
# result = df.groupby(\'address\')[\'id\'].count().reset_index()   # 确定一个属性
# print(result)

# 求个城市学生的平均值,最大值,最小值,分数总和
# 聚合agg(没有指定列名,就是对全部列进行计算)
# # df.groupby(\'address\')[\'score\'].mean().max()
# result = df.groupby(\'address\')[\'score\'].agg([\'mean\', \'min\', \'max\', \'sum\']).reset_index()
# print(result)

# 求各城市学生成绩的平均值和年龄的最大值
# print(df.groupby(\'address\').agg({\'score\': [\'mean\', \'max\'], \'age\': \'max\'}))

# 排序方法   True升序 by通过什么排序
# print(df.sort_values(by=\'age\', ascending=True))

# 计算某列中重复数据出现的频率
print(df[\'address\'].value_counts(), type(df[\'address\'].value_counts()))

6. dataframe中构造二维列表(常用于做可视化)

# 第一种
result = []
for index, value in temp.iterrows():
    print(index, \'---\', value), value[\'area\'], value[\'unit_price\']
    result.append(
        [
            value[\'area\'],
            round(value[\'unit_price\']/10000, 1)
        ]
    )
print(result)

# 第二种
result = [[value[\'area\'], round(value[\'unit_price\']/10000, 1)] for index, value in temp.iterrows()]

7. 创建透视表于交叉表(pivot_table,crosstab)

pivot_table

  • 透视表
pd.pivot_table(detail[[\'order_id\', \'counts\', \'amounts\']], index=\'order_id\', aggfunc=\'sum\').head(3)
pd.pivot_table(detail[[\'order_id\', \'dishes_name\', \'counts\']], index=\'order_id\', columns=\'dishes_name\',aggfunc=\'sum\').head(3)
pd.pivot_table(detail[[\'order_id\', \'dishes_name\', \'counts\']], index=\'order_id\', columns=\'dishes_name\',values=\'counts\', fill_value=0).head()

注意: pd.pivot_table(), 第一个参数是将要处理的数据全部写入,index确定行索引,columns确定列索引,values是要进行聚合的数据, aggfunc是聚合方法,默认np.mean, fill_value是修改默认值
crosstab

pd.crosstab(index=detail[\'order_id\'], columns=detail[\'dishes_name\']).head(3)
pd.crosstab(index=detail[\'order_id\'], columns=detail[\'dishes_name\'], values=detail[\'counts\'], aggfunc=\'sum\').fillna(0).head(3)

注意: pd.crosstab(), 不需要一开始就将全部数据导入, index=detail[\'order_id\']行索引, columns列索引, values要聚合的数据,aggfunc聚合的方法, 用fillna(0)填充,没有fill_value参数

分类:

技术点:

相关文章: