pandas

Series

  Series这种数据结构类似python中的列表,Series = 列表(value) + 标签(index),是一个一维的数据结构

 

通过列表构造Series

  s1 = pd.Series(["a", "b", "c", "d", "e"])

 

通过字典构造Series

  s2 = pd.Series({"name":"Tom", "age":15, "location":"China"})

 

通过切片获取特定的值

  s2.values[1:3]

 

获取s2的index值和value值

  s2.index

  s2.values

 

修改index值

  s1.index = ["one", "two", "three", "four", "five"]

 

修改values值

  s1[:] = ["A", "B", "C", "D", "E"]

 

通过位置索引获取并修改值

  s1[2] = "C"

 

通过index标签获取并修改值

  s1["two"] = "B1"

  s1[["one", "two"]] = ["Billy", "Apple"]

DataFrame

  DataFrame是一个具有行、行标签以及列、列标签的二维数据结构,类似于一个表格数据

 

通过列表创建DataFrame

  df = pd.DataFrame(["a", "b", "c"])

 

通过字典创建DataFrame

  df = pd.DataFrame({"小写":["a", "b", "c"], "大写":["A", "B", "C"]})

 

指定行标签和列标签

  df = pd.DataFrame([["one", "a"], ["two", "b"], ["three", "c"]], index=["一", "二", "三"], columns=["1列", "2列"])

 

修改某行或某列的标签,必须使用rename

  df.rename(index={"line2":"行2"}, inplace=True)

  df.rename(columns={"col1":"列1"}, inplace=True)

 

DataFrame基本属性

查询df的形状

  df.shape

 

获取df的行标签

  df.index

 

获取df的列标签

  df.columns

 

获取df的值

  df.values

 

进行行列转换

  df.T

 

获取df中指定列的值

  df["列名"]

 

统计df中指定列的数据个数,空值不计算在内

  df["列名"].value_counts()

 

看指定列有哪些唯一值

  df["列名"].unique()

 

统计指定列有多少个唯一值

  df["列名"].nunique()

 

返回df中每列的唯一值的个数

  df.nunique()

 

描述df中的基本情况,针对数值型的列有效

  df.describe()

 

查看df中每列数据类型等信息

  df.info()

 

查看df中前5行的值

  df.head()

 

查看df中后5行的值

  df.tail()

 

从excel文件中读取数据

  df = pd.read_excel(r"文件路径", sheet_name="Sheet1", header=None, names=["列1", "列2"],nrows=len(df), skiprows=[0])

 

切换当前工作路径

  import os

  os.chdir(r"文件路径")

 

读取指定列

  df = pd.read_excel(r"xxx.xlsx", usecols=["列1", "列2"])

  df = pd.read_excel(r"xxx.xlsx", usecols=[1, 2, 3])

 

指定列名为index

  df.pd.read_excel(r"xxx.xlsx", index_col="列名")

 

读取csv文件,引擎设置为python才能兼容utf8

  df = pd.read_csv(r"xxx.csv", engine="python", index_col=0, sep="#")

 

从文本文件中读取

  pd.read_table(r"xxx.txt", engine="python", sep="@")

 

数据预处理(数据清洗)通常包括

  1.缺失值(空值)处理;2.重复值处理;3.异常值处理;4.数据类型转换;5.索引设置

   查找缺失值思路,先看数据集中各列有没有缺失值,再看缺失值所占的比例,比例小可直接删除

 

查看每列数据的缺失值总数

  df.isnull().sum()

 

查看每列空值所占比例,5%以下可以考虑删除

  df.apply(lambda x: sum(x.isnull()) / len(x), axis=0)

 

删除带有缺失值的整行数据,一旦有缺失值就直接删除

  df.dropna(axis=0, how="any", inplace=False)

 

读取时替换默认的缺失值

  df = pd.read_excel(r"xxx.xlsx", na_values=["暂无", "未知"])

 

读取后在df中使用replace方法进行替换

  df.replace("暂无", np.nan, inplace=True)

 

如果售价中出现"万",该如何替换

  df["售价"].apply(lambda x: str(x).replace("万", "") if x is not np.nan else x).astype(np.float)

 

用平均值填充缺失值

  df.fillna({"售价": df["售价"].mean()})

 

删除重复值

  df.drop_duplicates(subset=["列名1", "列名2"], keep="first")

 

重置索引

  df.reset_index(drop=True)

 

异常值操作

异常值特征:异常值并不是错误值,是偏离正常范围的值。异常值出现频率较低,但会对实际分析造成误差

异常值检测:

  1.根据业务经验划定不同指标的正常范围,超过范围的值算异常值

  2.如果数据服从正态分布,可以用3sigma原则:一个数与平均值之间的偏差超过3倍标准差,则认定为异常值

  3.不符合正态分布的数据,一般通过绘制箱型图,把大于(小于)箱型图上边缘(下边缘)的点称为异常值

 

判断异常点的临界值

# 正的2倍标准差的点

except_high = df["weight"].mean() + 2 * df["weight"].std()

# 负的2倍标准差的点

except_low = df["weight"].mean() - 2 * df["weight"].std()

极端异常点的临界值

# 正的3倍标准差的点

extrme_except_high = df["weight"].mean() + 3 * df["weight"].std()

# 负的3倍标准差的点

extrme_except_low = df["weight"].mean() - 3 * df["weight"].std()

 

寻找异常值

df[(df["weight"] > except_high) | (df["weight"] < except_low)]

 

求1/4分位数

Q1 = df["count"].quantile(q=0.25)

求3/4分位数

Q3 = df["count"].quantile(q=0.75)

下界

low = Q1 - 1.5 * (Q3 -  Q1)

上界

high = Q3 + 1.5 * (Q3 -  Q1)

 

数据类型转换

数值类型转换

  df["售价"].astype(np.int32)

 

日期类型转换

  df["日期"] = pd.to_datetime(df["日期"], format="%Y-%m-%d")

  df["日期"].dt.year

  df["日期"].dt.day

 

读取文件时直接转换日期值

  df = pd.read_excel(r"xxx.xlsx", parse_dates=["要转为日期的列名"])

 

字符串类型处理

  df["部门"].str.replace("部", "组")

  df["部门"].str[:2]

 

索引设置

  df.columns = ["日期", "售价", "姓名", "部门"]

  df.index = ["a", "b", "c"]

 

设置特定的列作为行索引

  df.set_index("日期")

 

重置索引(针对层次化索引),将索引列当作普通的columns返回

  df.reset_index(level=0, drop=True)

 

筛选数据

选择单列

  df["售价"]

 

选择多列

  df[["售价", "日期"]]

 

通过列的位置索引选择列

  df.iloc[[0, 3, 4], 1:5]

 

通过位置标签选择

  df.loc[["a", "c", "f"], ["售价", "部门"]]

 

数值排序

  df.sort_values(by=["消费金额", "年龄"], ascending=[False, True])

 

数据删除,默认按照行来删

  df.drop(["消费金额", "年龄"], axis=1)

  df.drop(df.columns[[3, 4]], axis=1)

  df.drop(df.index[1:4])

 

插入新的行或列(插哪里,列名, 插什么值)

插入列

  df.insert(2, "新列", [i for i in range(10)])

 

插入到最后列

  df["再加一列"] = []

 

map函数用法

  for i in map(lambda x: str(x) + "ok", [1, 2, 3])

 

apply和applymap函数

apply针对某一行或某一列元素执行相同操作(Series对象)

  df["消费金额"].apply(lambda x: str(x) + "元")

  df.iloc[2].apply(lambda x: str(x) + "ok")

 

applymap是针对Dataframe中所有数据进行某种操作

  df.applymap(lambda x: str(x) + "ok")

 

数据运算

求众数(出现最多的数)

  df["sale2015"].mode()

 

求方差

  df["sale2015"].var()

 

时间序列

获取日期和时间

  from datetime import datetime

获取当前时间

  datetime.now()

获取当前年份

  datetime.now().year

获取当前月份

  datetime.now().month

获取当前星期

  datetime.now().weekday() + 1

  datetime.now().isocalendar() # 返回值格式(年,周,星期几)

 

指定时间格式

  datetime.now().strftime("%F")

 

时间序列查询(只有时间序列是行索引时才能操作)

  df["2019"]

  df["2019-08"]

  df["2019-08-01":"2019-08-11"]

  df[df["购买日期"] > datetime(2019, 8, 1)]

 

时间偏移

  from datetime import timedelta

构造时间

  date = datetime(2020, 3, 20, 20, 50)

时间往后移1天

  date + timedelta(days=1)

延后35秒

  date + timedelta(seconds=35)

 

pandas自带的库实现时间偏移

  from pandas.tseries.offsets import Day,Hour,Minute

  date = datetime(2020, 3, 20, 20, 50)

  date + Day(1)

  date + Hour(2)

  date + Minute(38)

 

DataFrame拼接,默认竖向拼接,横向拼接则加参数axis=1

  pd.concat([df1, df2], ignore_index=True, axis=0)

 

结果导出pd.to_xxx()

导出为excel文件(首先要安装pip3 install openpyxl)

  df.to_excel("导出文件.xlsx", index=False)

 

设置需要导出的列

  df.to_excel("xxx.xlsx", index=False, columns=["列1", "列2"])

 

注:浮点数要转换为字符串之后,才能进行replace

 

导出时的缺失值处理(缺失值设为0)

  df.to_excel("xxx.xlsx", index=False, na_rep=0)

 

导出csv文件

  df.to_csv("xxx.csv", sep=",", index=False)

 

数据可视化matplotlib

  import matplotlib.pyplot as plt

  %matplotlib inline

  plt.rcParams["font.sans-serif"] = "SimHei" # 中文显示

  plt.rcParams["axes.unicode_minus"] = False # 解决负号无法显示问题

  %config InlineBackend.figure_format = "svg" # 显示更清晰

 

建立和绘制画布和坐标系

创建一个宽为8,高为6的画布

  fig = plt.figure(figsize=(8, 6))

 

在画布上创建坐标系

  1.add_subplot()

    ax1 = fig.add_subplot(1, 1, 1) # 创建1行1列的坐标系,坐标系序号为1

  2.plt.subplot2grid()

    plt.subplot2grid((2, 2), (0, 0)) # 生成2行2列坐标系,且在(0, 0)位置

  3.plt.subplot()

    plt.subplot(2, 2, 1) # 生成2行2列坐标系,坐标系序号为1

  4.plt.subplots()

    fig, axes = plt.subplots(2, 2)

    

设置坐标轴的标题

  plt.xlabel("xxxx", labelpad=5, fontsize=16, color="r", fontweight="bold")

  plt.ylabel("xxxx")

 

设置坐标轴刻度

  plt.xticks(x, [(str(i) + "月") for i in range(1, 7)])

  plt.yticks()

 

设置网格线

  plt.grid(axis="x")

 

设置图例

  plt.legend(loc="best")

 

设置标题

  plt.title("xxxx", loc="center")

 

设置数据标签

  plt.text(x坐标的值, y坐标的值, "文字内容")

  for a, b in zip(a, b):

    plt.text(a, b, b, ha="center", va="bottom", fontsize=8)

 

柱状图

  plt.bar(x, y, width=0.5, align="center", label="xxxx")

 

条形图

  plt.barh(x, height=0.5, width=y, align="center")

 

直方图,观察数据的分布形态,主要用于连续型变量

  ser = pd.Series(data)

  ax = ser.plot(kind="hist", bins=20, facecolor="r", edgecolor="black", alpha=0.6)

  ser.plot(kind="kde", ax=ax, secondary_y=True) # 核密度图

 

等距划分

  pd.cut(df["列名"], bins=20)

 

箱型图

  plt.boxplot(df["列名"],

      patch_artist=True # 是否进行箱体填充

      , showmeans=True # 是否显示均值线

      , showfliers=True # 是否显示异常值

      , boxprops={"color":"b", "facecolor":"yellow"} # 设置箱体属性,如颜色

      , flierprops={"marker":"o", "markerfacecolor":"r"} # 设置异常值属性

      , labels=[""]) # 让x轴不显示刻度值

 

散点图,发现变量间的相关关系

  plt.scatter(x, y, marker="o", s=50)

 

蚂蚁学python

pandas读取数据

读取csv
  df = pd.read_csv("xxx.csv")

 

查看前几行
  df.head()

 

查看数据的形状
  df.shape

 

查看列名列表
  df.columns

 

查看索引列
  df.index

 

查看每列的数据类型
  df.dtypes

 

读取txt文件
  df = pd.read_csv(fpath, sep="\t", header=None, names=["", "", ""])

 

读取excel
  df = pd.excel("xxx.xlsx")

 

读取mysql
  import pymysql
  conn = pymysql.connect(host="", port="", user="", password="", database="", charset="utf8")
  df = pd.read_sql("sql语句", con=conn)

  DataFrame:二维数据,整个表格,多行多列
  Series:一维数据,一行或一列

 

创建

列表创建Series
  pd.Series([])

 

获取索引
  s.index

 

获取数据
  s.values

 

创建Series时,指定index
  pd.Series([], index=[])

 

字典创建Series,key变索引,value变values
  pd.Series({})

 

字典创建DataFrame,key变列标签,value变values
  pd.DataFrame({"xxx":[], "xxx":[], "xxx":[]})

 

查询

查询一列
  df["列名"]

 

查询多列
  df[["列1", "列2"]]

 

查询一行
  df.loc[1]

 

查询多行(loc包含末尾元素)
  df.loc[1:3]

 

设定索引为日期,方便按日期筛选
  df.set_index("ymd", inplace=True)

 

替换掉温度的后缀℃
  df.loc[:, "wendu"] = df["wendu"].str.replace("℃", "").astype("int32")

 

1.得到单个值
  df.loc["2018-01-03", "wendu"]

 

2.给列传入一个列表,得到一个Series
  df.loc["2018-01-03", ["bwendu", "ywendu"]]

 

给行传入一个列表,得到一个Series
  df.loc[["2018-01-03", "2018-01-05"], ["wendu"]]

 

给行和列传入一个列表,得到一个DataFrame
  df.loc[["2018-01-03", "2018-01-05"], ["bwendu", "ywendu"]]

 

3.行按区间查询
  df.loc["2018-01-03":"2018-01-05", "wendu"]

 

列按区间查询
  df.loc["2018-01-03", "bwendu":"fengxiang"]

 

行和列都按区间查询
  df.loc["2018-01-03":"2018-01-05", "bwendu":"fengxiang"]

 

4.使用条件表达式查询
  df.loc[df["wendu"] < 10, :]

 

5.调用函数查询(这时,把每一行的Series传给df)
  df.loc[lambda df: (df["bwendu"]<=30) & (df["ywendu"]>=15), :]

 

自己写函数,查询9月空气质量好的数据
  def query_data(df):

    # 对每一行进行处理
    return df.index.str.startswith("2018-09") & df["aqiLevel"] == 1
  df.loc[query_data, :]

 

新增数据列

1.直接赋值

  df.loc[:, "wencha"] = df["bWendu"] - df["yWendu"]

 

2.apply方法

  def get_wendu_type(x):

    if x["bWendu"] > 33:

      return "高温"

    elif x["yWendu"] < 10:

      return "低温"

    return "常温"

df.loc[:, "wendu_type"] = df.apply(get_wendu_type, axis=1)

 

3.assign方法(可以同时新增多个列)

  df.assign(

    yWendu_huashi = lambda x: x["yWendu"] * 9 / 5 + 32,

    bWendu_huashi = lambda x: x["bWendu"] * 9 / 5 + 32

  )

 

4.按条件选择分组分别赋值

  df["wencha_type"] = ""

  df.loc[df["bWendu"] - df["yWendu"] > 10, "wencha_type"] = "温差大"

  df.loc[df["bWendu"] - df["yWendu"] <= 10, "wencha_type"] = "温差正常"

 

统计函数

描述

  df.describe()

 

查看单个Series

  df["bWendu"].mean()

 

唯一去重

  df["tianqi"].unique()

 

按值计数

  df["fengxiang"].value_counts()

 

协方差

  协方差为正,说明x和y同向变化,协方差越大,同向程度越高

  协方差为负,说明x和y反向运动,协方差越小,反向程度越高

  df.cov()

 

相关系数

  df.corr()

 

单独看两个变量的相关系数

  df["aqi"].corr(df["yWendu"])

 

缺失值处理(检测、删除、填充)

检测空值

  df.isnull()

  df["列名"].isnull()

 

检测不为空值

  df["列名"].notnull()

 

筛选没有空分数的所有行

  df.loc[df["score"].notnull(), :]

 

删除全是空值的列

  df.dropna(axis="columns", how="all", inplace=True)

 

删除全是空值的行

  df.dropna(axis="index", how="all", inplace=True)

 

将分数列为空的值填充为0分

  df.fillna({"分数": 0})

  df.loc[:, "分数"] = df["分数"].fillna(0)

 

将姓名的缺失值用前面的有效值填充

  df.loc[:, "姓名"] = df["姓名"].fillna(method="ffill")

 

将清洗好的excel保存

  df.to_excel("xxx.xlsx", index=False)

 

SettingsWithCopyWarning解决方案

原因:在子的dataFrame中设置新列,如:

condition = df["ymd"].str.startswith("2018-03")

df[condition]["wencha"] = df["bWendu"] - df["yWendu"]

链式操作其实是2个步骤,先get后set,get得到的dataFrame可能是view,也可能是copy

pandas的DataFrame修改写操作,只允许在源DataFrame上进行,并且要一步到位

 

解决方法1:将get和set两步操作,改成set的一步操作

df.loc[condition, "wencha"] = df["bWendu"] - df["yWendu"]

 

解决方法2:使用copy复制DataFrame

df_month3 = df[condition].copy()

df_month3["wencha"] = df["bWendu"] - df["yWendu"]

总之,pandas不允许先筛选子DataFrame再进行修改写入

 

排序

Series排序

  s.sort_values(ascending=False, inplace=True)

 

DataFrame排序

  df.sort_values(by=["列名"], ascending=True, inplace=True)

 

字符串处理

1.使用方法:先获取Series的str属性,然后在属性上调用函数

2.只能在字符串列上使用,不能在数字列上使用

3.DataFrame上没有str属性和处理方法

4.Series.str并不是python原生字符串,而是自己的一套方法,不过大部分和原生str很相似

 

字符串替换函数

df["bWendu"].str.replace("℃", "")

 

判断是不是数字

df["bWendu"].str.isnumeric()

 

使用str的startswith、contains等得到bool的Series可以做条件查询

  df[df["ymd"].str.startswith("2018-03")]

 

链式操作,从月份中提取字符串"201803"

  df["ymd"].str.replace("-", "").str[0:6]

 

正则替换

  df["中文日期"].str.replace("[年月日]", "")

 

axis参数理解

axis=0或者axis="index":如果是单行操作,指的是某一行。如果是聚合操作,指的是跨行cross rows

axis=1或者axis="columns":如果是单列操作,指的是某一列。如果是聚合操作,指的是跨列cross columns

 

删除列

  df.drop("列名", axis=1)

 

删除行

  df.drop("行名", axis=0)

 

用index查询数据

df.set_index("userId", inplace=True, drop=False)

df.loc[500]

 

merge用法

pd.merge(left, right, how="inner", on="None", left_on=None, right_on=None)

 

数据合并concat

pd.concat([df1, df2], axis=0, join="outer", ignore_index=False) # outer:不匹配的也会展示

 

利用concat新增列

pd.concat([s1, df, s2], axis=1)

 

df.append(other, ignore_index=False) # append只能按行合并,相当于concat的简写形式

 

一行一行给df添加数据

pd.concat(

  [pd.DataFrame([i]), columns=["A"] for i in range(5)], ignore_index=True

)

 

忽略报警

import warnings

warning.filterwarnings("ignore")

 

groupby分组统计

df.groupby("列名").sum()

df.groupby(["列1", "列2"]).sum()

 

列名不会变为行索引

  df.groupby(["列1", "列2"], as_index=False).mean()

 

同时查看多个聚合函数

  df.groupby("列1").agg([np.sum, np.mean, np.std])

 

查看单列的结果数据统计(2种方法)

  df.groupby("列1")["列2"].agg([np.sum, np.mean, np.std])

  df.groupby("列1").agg([np.sum, np.mean, np.std])["列2"]

 

不同列使用不用的聚合函数

  df.groupby("列1").agg({"列2":np.sum, "列3":np.mean})

 

分层索引

unstack把二级索引变成列

  ser.unstack()

 

把索引都变成列

  ser.reset_index()

 

多层索引,可以用元组进行筛选

  ser.loc["baidu"]

  ser.loc["baidu", "2019-10-02"]

  ser.loc[:, "2019-10-02"]

 

DataFrame设置分层索引

  df.set_index(["公司", "日期"], inplace=True)

DataFrame筛选数据

  当传入元组(key1,key2)时,代表筛选多层索引,key1是一级索引,key2是二级索引。比如key1=JD,key2=2019-10-02

  当传入列表[key1, key2]时,代表同一层的多个KEY,key1和key2是并列的同级索引。比如key1=JD,key2=baidu

 

slice(None)代表筛选这一索引的所有内容

  df.loc[(slice(None), ["2019-10-02", "2019-10-03"]), :]

 

把多级索引变为普通列

  df.reset_index()

 

数据转换函数map、apply、applymap

map:只用于Series,实现每个值->值的映射

apply:用于Series实现每个值的处理,用于DataFrame实现某个轴的Series的处理

applymap:只能用于DataFrame,用于处理该DataFrame的每个元素

 

将股票代码英文转为中文

方法1:Series.map(dict)

  dic = {"baidu":"百度", "ali":"阿里", "aqy":"爱奇艺", "jd":"京东"}

  df["公司"].str.lower().map(dic)

 

方法2:Series.appy(function)

  df["公司"].apply(lambda x: dic[x.lower()])

 

方法3:DataFrame.apply(function, axis=1),此时的x是一个Series

  df.apply(lambda x: dic[x["公司"].lower()], axis=1)

 

applymap实现所有值的转换

  df.applymap(lambda x: int(x))

 

对分组后的每个分组应用apply

  df.groupby("列名").apply(function)

 

扩展:归一化

  x_norm = (x - x.min()) / (x.max() - x.min())

 

pandas快速实现周、月、季度的日期聚合统计

将日期序列设置为行索引

筛选3月数据

  df.loc["2020-03"]

 

周数字列表

  df.index.week

 

月数字列表

  df.index.month

 

季度数字列表

  df.index.quarter

 

查看每周最高温度

  df.groupby(df.index.week)["最高温度"].max()

 

pandas处理日期索引的缺失

将df的索引设置为日期索引

  df.set_index(pd.to_datetime(df.index))

 

生成完整的日期序列

  pdates = pd.date_range(start="2020-06-01", end="2020-06-20")

 

重置索引

  df_new = df.reindex(pdates, fill_value=0)

 

重采样

  df.resample("2D").mean() # 每2天采样求平均

 

pandas计算同比和环比

先把数据处理成:行索引为日期月格式df.resample("M"),values为一列

增加环比增长和同比增长列

  df["环比增长"] = df["销售额"].pct_change(periods=1)

  df["同比增长"] = df["销售额"].pct_change(periods=12)

posted @ 2020-03-29 14:40  echonick555  阅读(212)  评论(0)    收藏  举报