• Pandas练手项目


    一、chipotle tsv

    数据集chipotle.tsv-数据集

    代码:https://download.csdn.net/download/Albert233333/88508819

    1 导入数据,tab分割

    有的数据文件是用tab来分开的,读取的时候用下面这个参数

    1. # order_id这一列相同的数字表示 一个消费者同一次进行的交易
    2. # 表格中的每一行表示 用户一次购买的某一个品类 购买的数量
    3. # 消费者可能一次购买很多个不同种类的东西,所以你会发现有好几行的item_name不同,但是order_id完全相同。
    4. # 这都是同一个用户在同一个时间购买的(所以order_id完全相同),只不过购买的物品的种类不同(item_name不同)
    5. import pandas as pd
    6. d = pd.read_csv("chipotle.tsv",delimiter="\t")
    7. d

    2 找出下单数最多的 item

    降序排列用sort_values

    1. # 这里仅仅统计的是单个
    2. d.sort_values('quantity',ascending=False)

    如果你要按照某一列为合并的标准,自行选择合并的方式(求和、均值、max,min)用groupby

    你要按照某一列的类别(比如这一列了有薯片、瓶装水、火鸡、沙拉等等商品类别,很多个用户有的买了这个,有的买了那个,你想算出火鸡一共卖了多少件,瓶装水一共卖了多少件),求每个类别的 求和、均值、max,min,用groupby

    d.groupby("item_name").sum()[["quantity"]].head()

    1. # 按照销售量最高排序
    2. d.groupby("item_name").sum()[["quantity"]].sort_values(by="quantity", ascending=False)

    3 将字符串的某一列移除开头的字符,整列从str转float

    打印出在该数据集对应的时期内的收入(revenue)数额 

    收入=销量*价格

    item_price这一列,每个数字钱都有  $  这个符号,要去掉。然后把整列从str转成float,方便后面的计算。

    1. # 第一部分“.str.lstrip("$")”,是将这一列字符串中所有的第一个元素删掉
    2. # 具体来说是删掉左边的 “$”字符
    3. # 第二部分 “.astype(float)”将这一列所有的元素都转成浮点数
    4. d["item_price"].str.lstrip("$").astype(float)

    销量与价格相乘再求和,就是总收入

    sum(d["quantity"]*d["item_price"].str.lstrip("$").astype(float))

     二、Titanic

    数据集:https://download.csdn.net/download/alienwh329/16680606

    代码:https://download.csdn.net/download/Albert233333/88509830

    1 将某列设置为索引

    df.set_index("PassengerId")

    2 绘制扇形图

    绘制一个展示男女乘客比例的扇形图

    得出男女的具体数字

    1. sex_per = df["Sex"].value_counts()
    2. sex_per

    1. # 把画图的包导入进来
    2. import matplotlib.pyplot as plt
    3. # 这种绘图方式主要用于有多个子图以及复杂的图形布局的时候。
    4. fig,ax = plt.subplots()
    5. # plt.subplots() 会创建一个新的图形(figure)和对应的轴(axes)对象。
    6. # 这个函数返回一个元组,第一个元素是图(figure),第二个元素是轴(axes)。
    7. # fig 是用来设置图形的一些全局属性,比如标题、坐标轴范围等。
    8. # ax 是一个包含两个轴的子图对象,可以用于绘制图形。
    9. ax.pie(sex_per, labels=sex_per.index)
    10. #
    11. # 第一个参数是,绘图的数据
    12. # 第二个参数是图中的标签,这句话亦可 ax.pie(sex_per, labels=["male","female"])
    13. ax.set_title("Pie Chart")
    14. plt.show()
    15. # 用于在用户界面中打开一个窗口来显示绘制的图形。
    16. # 如果你在绘图过程中省略了plt.show(),那么图形可能不会以预期的方式显示出来。
    17. # 这是因为plt.show()会触发图形的渲染和显示过程。
    18. # 在一些情况下,例如在Jupyter Notebook或IPython中,plt.show()可能不是必需的,
    19. # 因为图形会自动显示。但在其他环境中,例如在脚本或Python交互式解释器中,使用plt.show()是必要的,否则图形将不会显示。
    20. # 因此,虽然plt.show()不是绝对必需的,但在绘图过程中通常建议使用它以确保图形正确显示。

     

    1. # 没有多个子图的时候直接用plt绘图即可
    2. plt.pie(sex_per, labels=sex_per.index)
    3. ax.set_title("Pie Chart")
    4. plt.show()

     

    3 绘制散点图

     绘制一个展示票价 Fare, 与乘客年龄和性别的散点图

    1. # 票价与年龄 的散点图
    2. # 用ax绘图,把横纵坐标的数据输入进去
    3. plt.scatter(df["Fare"],df["Age"])
    4. # 添加标题
    5. plt.title(" Fare vs Age")
    6. # 横坐标的标签
    7. plt.xlabel("Fare")
    8. plt.ylabel("Age")
    9. # 纵坐标的标签
    10. plt.show()

    将文字的某一列(“男”和“女”)转成数字

    1. # 使用map,用一个函数进行映射,将字符串转成数字
    2. Sex = df.Sex.map(lambda x: 0 if x=='male' else 1)
    3. Sex

     4 绘制直方图

    1. plt.hist(df.Fare)
    2. plt.title("The histogram of Fare")
    3. plt.xlabel("Fare")
    4. plt.ylabel("Frequency")

     

    5 柱状图

    1. import matplotlib.pyplot as plt
    2. # 数据
    3. # 每一个柱子的名字
    4. bars = ('A', 'B', 'C', 'D', 'E')
    5. # 横坐标每一个数字,实际的数字
    6. x_pos = range(len(bars))
    7. # 柱子的高度
    8. height = [3, 7, 2, 5, 6]
    9. # 创建柱状图
    10. # 第一个参数写横坐标的真实数字,第二个参数写柱子的高度
    11. plt.bar(x_pos, height)
    12. # x轴上 每个真实的数字,对应的替换的字母名字
    13. plt.xticks(x_pos, bars)
    14. # 显示图像
    15. plt.show()

    三、wind.data

    1 导入数据间距不同的数据集

    数据集:https://download.csdn.net/download/Albert233333/88509854

    代码:https://download.csdn.net/download/Albert233333/88509873

    数据集每一行,列与列之间的的空格数量都不同,

            像下面,表头有得间距1个空格,有的间距3个

            后面的数据,他为了对齐,有得间距3个空格,有得间距1个空格

     如果强行导入是这样,所有的标题是在一格里,所有的数据都在一格里

    1. df = pd.read_csv("wind.data")
    2. df

    这个时候你发现每一行,每一个格的内容是一个超级长的字符串,字符串里 数据集用 不确定的多个空格分割,长下面这样

    先使用pd.Series下面的str的功能把字符串  以 一个空格 来分割 成一个列表

    1. d = df["Yr Mo Dy RPT VAL ROS KIL SHA BIR DUB CLA MUL CLO BEL MAL"].str.split(pat=" ")
    2. d

    每一行都是下面这样的列表

     我们可以发现,拆分成的列表,里面有很多个空的字符串。这是因为前面说的  数字和数字之间有时候有1个空格,有时候有2个空格,有的时候3个空格。按照空格拆分,就会拆分出空格和空格之间的 空字符串。

    所以需要通过apply函数,对pd.Series中每一个都是用lambda函数,如果不是空格才保留

    1. d = d.apply(lambda x:[i for i in x if i!= ""])
    2. d

    拆分以后,果真空的的字符串在列表里消失了 

    这个时候我们发现,d就是一个pd.Series(),每个元素都是一个列表。

    我们的目的是希望把数据集转成一个多列多行的DataFrame。像下面这样。每一列表示数据的一个维度

     为了实现这个目的,先把这个pd.Series转成一个多维列表,然后再转成DataFrame

    1. # 将一列DataFrame变成多列最好的方式,先转列表,再转DataFrmae
    2. d = pd.DataFrame(list(d))
    3. d

     改好column name

    1. # 在Python中,字符串对象的strip()方法是用于删除字符串
    2. # 开头和结尾的空白字符(包括空格、换行符\n、制表符\t等)。
    3. # 具体来说,strip()方法会返回一个新字符串,其中已删除给
    4. # 定字符串的开头和结尾的空白字符。如果字符串中没有空白字符,则返回原始字符串。
    5. col = df.columns[0].split(" ")
    6. # 在Python中,字符串类型的值""(空字符串),被视为布尔类型的False。
    7. # 当使用if语句进行条件判断时,如果条件为False,则不会执行if下面的命令。
    8. # 因此,当i = ""时,i.strip()的结果仍然为"",即布尔类型的False。
    9. # 在if语句中,由于条件为False,因此不会执行if下面的命令。
    10. # 空字符串就删掉了
    11. col = [i for i in col if i.strip()]
    12. col

    1. d.columns = col
    2. d

    2 在日期每个数字前,加上19,变成1961

    原来的日期是这样的,在前面加上19,变成1961

     

    在字符串“61”前面加上字符串“19”,然后把字符串“1961”转成数字1961

    1. d["Yr"] = d["Yr"].apply(lambda x:int("19"+x))
    2. d

    3 将字符串的日期 改为 datetime64类型,并设为索引 

    将Yr Mo Dy这三列合并成   有年月日  的一列

    1. # 将三列拼接成一列的最好方法
    2. # 这里astype()是把表格中数据转换类型
    3. d["date"] = d["Yr"].astype(str) + "-" + d["Mo"].astype(str) + "-" + d["Dy"].astype(str)
    4. d

    1. # 将date这一列转成datetime64的类型,再替换回去
    2. d["date"] = pd.to_datetime(d["date"])
    3. d

    验证是否转成功了

    d["date"] # 果然数据类型变成的datetime64的数据类型

     

    1. # 将date 这一列设定为index
    2. d.set_index("date")

     

    4 将数据中字符串的NaN转成np.nan

    1. d = d.set_index("date")
    2. # DataFrame里面所有的数字都是字符串类型,并且有些还是字符串类型的“NaN”,如何迅速将DataFrame中所有的东西的类型转成float类型
    3. d = d.apply(pd.to_numeric, errors='coerce')
    4. d
    5. # 这里apply表示对于DataFrame中每一个元素都执行后面函数里的操作
    6. # pd.to_numeric这个是函数的名字,函数里面对于一个参数的定义写在后面了,“errors='coerce'”
    7. # 正常这个函数是这样用,pd.to_numeric(errors='coerce')
    8. # 在 pd.to_numeric 函数中,参数 errors 可以控制当转换失败时该如何处理。
    9. # 当 errors='coerce' 时,无法成功转换的值会被设置为 NaN(Not a Number)。
    10. # 这是一种比较强硬的错误处理方式,它会直接将无法转换的值从数据集中移除。
    11. # 当 errors='raise' 时,如果遇到无法转换的值,函数会抛出一个错误,并停止执行。
    12. # 这是一种比较保守的处理方式,可以防止错误值污染整个数据集。

    5 删除某几列

    1. # axis=1删除一列
    2. d = d.drop(['Yr', 'Mo','Dy'], axis=1)
    3. d

     

     6 计算每一列的平均值

    1. # 每一个地区这6500天的平均风值
    2. d.mean(axis=0)

    7 有1961-1978年每天的风速数据,要求你计算这18年每年1月的平均风速 

    先把1月份的数据从这18年的数据总表中取出来

            pd.Series自带识别每个日期是几月的功能

    pd.Series(d.index).dt.month

    先把1月的数据取出来 

    1. # 先把date这一列恢复
    2. d = d.reset_index()
    3. # 把第一个月的数据取出来
    4. jan = d[d["date"].dt.month==1]
    5. jan

     

    然后再使用groupby按照年来分组,然后按年取平均

    jan.groupby(pd.Grouper(key="date",freq="Y")).mean()

    上面这个结果的index我只想显示年份,不想显示月和日,采用下面的操作

            pd.Series里面有dt这个功能可以自动提取年份

    1. # 以年份为分组的标准,按年取平均
    2. jan_mean = jan.groupby(pd.Grouper(key="date",freq="Y")).mean()
    3. # 只保留日期中的年 这个数据,月和日移除掉
    4. jan_mean.index = pd.Series(jan_mean.index).dt.year
    5. jan_mean

    验证一下上面计算的对不对,求一下1961年所有地方的平均风速

            可以通过pd.Series.dt来指定年份

    1. jan[jan[["date","RPT"]]["date"].dt.year==1961].mean(axis=0)
    2. # 经过计算上面的结果一样。说明上面计算的结果是对的

     

    8 对于数据,分别以年、月为频率取样resample

    d.resample("M").mean()

    上面计算一月份平均风速用这个更简便,计算出每个月的平均风速以后,再把一月的取出来即可 

    d.resample("Y").mean()

    四、 second_cars_info.csv

    数据集:https://download.csdn.net/download/Albert233333/88510316

    代码:https://download.csdn.net/download/Albert233333/88510323

    数据集长这样

     

     1 选取上牌日期在2015年1月1日到2016年1月1日的数据

    Boarding_time本来是这样,string类型的

    按照字符串的年和月解析,把年和月的数字解析出来,转成datetime64格式

             未上牌的,先转成np.nan

    1. # 用replace函数将前面的替换成后面的
    2. c["Boarding_time"]= c["Boarding_time"].replace("未上牌",np.nan)

            转datetime64

    1. # 因为“Boarding_time”中
    2. # 将Boarding_time这一列从“2011年5月”这种带汉字的文字格式转换成datetime64
    3. # 第一个参数是被转换的原始数据,第二个参数是这一列里面日期的格式。代码会根据这个格式自动转换
    4. c["Boarding_time"] = pd.to_datetime(c["Boarding_time"],format="%Y年%m月")
    5. # 你也可以直接用下面这句话,就不需要做前面replace这一步了。直接将不可转换的东西替换成np.nan
    6. # c["Boarding_time"] = pd.to_datetime(c["Boarding_time"],format="%Y年%m月", errors="coerce")

     选取上牌日期在2015年1月1日到2016年1月1日的数据

    1. c[(c["Boarding_time"]>"2015-01-01") & (c["Boarding_time"]<"2016-01-01")]
    2. # 你注意上面的运算符不能使用and,因为这样Python会试图对整个表达式进行求值,继而引发报错
    3. # 你应该使用为DataFrame和Series是自己的逻辑运算方法 &
    4. # 更便捷的是使用pandas内置的方法来实现.一句话搞定
    5. # df_filtered = c[c['Boarding_time'].between(pd.to_datetime('2014-01-01'), pd.to_datetime('2015-01-01'))]

    2 写个函数构建查询引擎,收入对于每个维度的条件,把符合条件的dataframe筛选出来

     这函数用于将你输入的  >=某个条件  转化成有True和False的掩码表

    1. def parse_operator(oprt,col,num):
    2. if oprt == '>=':
    3. # return lambda x, y: col >= num
    4. return col >= num
    5. elif oprt == '<=':
    6. # return lambda x, y: col <= num
    7. return col <= num
    8. # 添加其他运算符...
    9. else:
    10. raise ValueError('Invalid operator.\n大小一律只许 >= 和 <= 不允许有其他的符号\n两个条件之间用 " and "连接,\n大于号或小于号在左边,数字在右边')
    11. # 如果你只想有一个条件,请写两个完全相同条件进去,比如Km=">=5 and >=5"即可')

    根据你的两个条件输出 最终的 mask掩码表

    1. # c是原始数据
    2. # oprt_s是进来的那个运算符的字符串
    3. # col_name 是要按照条件去的那一列的 列名
    4. #
    5. def mask_gen(c, oprt_s,col_name,if_date=False):
    6. # 注意这里不可以使用if Km != no_rq:,因为no_rq是一个pd.Series,
    7. # 不能用python的运算符,判断与这个类型是否相等应该用equals,也就是下面这句话
    8. if not no_rq.equals(oprt_s): # 判断Km不是全是True的一个Series,也就是有一些条件在里面
    9. # 上面这句话也可以用if isinstance(Km, str),效果一样
    10. # print("1"*100)
    11. # 默认的格式是要求填入两个条件,拆分成两个字符串
    12. s1, s2= oprt_s.split(" and ")
    13. # 将每一个条件,拆分成 >= 和 数字
    14. # print(s1[2:])
    15. # print(s2[2:])
    16. oprt1, oprt2 = s1[0:2], s2[0:2]
    17. # 如果说不是日期,正常转float即可
    18. if not if_date:
    19. num1, num2 = float(s1[2:]), float(s2[2:])
    20. # 如果是日期,就直接用原始的字符串即可
    21. else:
    22. num1, num2 = s1[2:], s2[2:]
    23. # 分别得到两个条件的mask表
    24. mask1 = parse_operator(oprt1, c[col_name], num1)
    25. mask2 = parse_operator(oprt2, c[col_name], num2)
    26. # print(mask1)
    27. # print(mask2)
    28. mask= (mask1 & mask2)
    29. # print(mask)
    30. return mask

    最终写好的engine函数

    1. # 第一个参数表示输入进去的数据,全是True
    2. # 第二个参数用index来调整整个Series的大小
    3. # c.shape[0] 表示True的行数
    4. no_rq = pd.Series(True, index=range(c.shape[0]))
    5. # 如果你默认不输入这个条件,就获取到这个条件所有的数据,变成一个全是True的Series即可
    6. def engine(c,Brand=no_rq, Name=no_rq, Boarding_time=no_rq, Km=no_rq, Discharge=no_rq, Sec_price=no_rq, New_price=no_rq):
    7. # 直接按字符匹配的有Brand,Name,Discharge
    8. # 如果这项条件你都定义了才做条件筛选
    9. if isinstance(Brand,str):
    10. Brand = c["Brand"]==Brand
    11. if isinstance(Name,str):
    12. Name = c["Name"]==Name
    13. if isinstance(Discharge, str):
    14. Discharge = c["Discharge"]==Discharge
    15. # 其他需要匹配大小和区间的变量:Km,Sec_price,New_price
    16. # print(Km)
    17. if isinstance(Km, str):
    18. Km = mask_gen(c,Km,"Km")
    19. if isinstance(Sec_price,str):
    20. Sec_price = mask_gen(c, Sec_price,"Sec_price")
    21. if isinstance(New_price,str):
    22. New_price = mask_gen(c, New_price,"New_price")
    23. if isinstance(Boarding_time,str):
    24. Boarding_time = mask_gen(c,Boarding_time,"Boarding_time",if_date=True)
    25. # 每个变量的两个条件和一个条件的情况,首先识别,其次两个条件的要合并
    26. # 最后,不同的条件,如何同时起作用。 把这些条件的掩码表,& 在一起,即可
    27. # results = c[Brand & Name & Discharge & Boarding_time & Km & Discharge & Sec_price & New_price]
    28. results = c[Brand & Name & Discharge & Km & Sec_price & New_price & Boarding_time]
    29. return(results)
    30. # engine(c,Brand="奥迪",
    31. # Name="奥迪A6L 2014款 30 FSI 豪华型",
    32. # Discharge="国4,国5",
    33. # Km=">=0.01 and <=1"
    34. # )
    35. #

    engine这样使用,使用的规则写在下面的注释里面了

    1. engine(c,
    2. Name="宝马3系 2007款 320i豪华型",
    3. Km=">=7 and <=9",
    4. Sec_price=">=7 and <=9",
    5. New_price=">=40 and <=50",
    6. Boarding_time=">=2007-01-01 and <=2008-08-31")
    7. # 大小一律只许 >= 和 <= 不允许有其他的符号,两个条件之间用 " and "连接, 大于号或小于号在左边,数字在右边
    8. # 如果你只想有一个条件,请写两个完全相同条件进去,比如Km=">=5 and >=5"即可
    9. # 注意关于日期,必须按照这个日期的格式进行输入"2015-01-01"

    按照上面写的条件,识别出来的复合条件的数据如下

  • 相关阅读:
    【无标题】
    python 裁剪图片并保存
    微服务学习|Nacos配置管理:统一配置管理、配置热更新、配置共享、搭建Nacos集群
    macOS 下JD-GUI报JDK1.8+的问题
    HTTPS双向认证和如何生成证书
    Dao、Dto、Entity和pojo、mapper概念及关系
    【ROS2原理2】必须要ROS2系统的四个要求
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java扶贫产品和扶贫物资捐赠系统r32rk
    PHP反序列化简单使用
    maven打包时,如何构建docker镜像,并推送到私有docker仓库
  • 原文地址:https://blog.csdn.net/Albert233333/article/details/134253027