pandas 基本操作

概述python 的 pandas 库用来处理表格类型(也就是矩阵)的数据非常方便, 这个库用来在可视化之前对数据进行变换,计算和汇总之类的操作再好不过 。
下面整理了最近我在做数据分析的短视频时常用的一些方法 。
读取数据文件做视频之前,我采集的数据都是用 csv 格式保存的,这里主要演示 pandas 库的 read_csv 方法 。
读取其他文件格式的方式类似,主要是函数名称不同,参数都差不多 。
读取 csv 文件读取 csv 文件非常简单,指定 csv 文件的路径即可 。测试用 csv 文件内容如下:
【pandas 基本操作】IP地址,手机号,登录日期223.104.147.75,19951762925,"2021-04-15 01:33:08"117.181.52.75,15873565020,"2021-04-15 01:48:24"42.49.165.99,18673535620,"2021-04-15 02:14:40"14.116.141.24,18673535620,"2021-04-15 05:01:40"# -*- coding: utf-8 -*-import pandas as pddef test():df = pd.read_csv("~/share/test.csv",)print(df)if __name__ == "__main__":test()程序运行结果:
$ python test.pyIP地址手机号码登录日期0223.104.147.751.995176e+102021-04-15 01:33:081117.181.52.751.587357e+102021-04-15 01:48:24242.49.165.991.867354e+102021-04-15 02:14:40314.116.141.241.867354e+102021-04-15 05:01:40读取之后修改列的名称,指定列的类型csv 文件中的列名有时候没有,或者有时候是中文的,列名是后续进行操作数据时使用的 key,一般在读取时将其转换成英文 。
同时,可以看出手机号码默认被当成数值类型了,所以用科技计数法来表示,在读取数据时,可以设置此列为字符串类型 。
# -*- coding: utf-8 -*-import pandas as pddef test():df = pd.read_csv("~/share/test.csv",skiprows=[0],names=["ip", "mobile", "login_date"],dtype={"mobile": str},)print(df)if __name__ == "__main__":test()

  1. skiprows 可以用来忽略第一行标题,因为我们用 names 指定了新的标题名称 。
  2. dtype 用来指定某列的类型,不指定的话,系统自动推断类型 。
程序运行结果:
$ python test.pyipmobilelogin_date0223.104.147.75199517629252021-04-15 01:33:081117.181.52.75158735650202021-04-15 01:48:24242.49.165.99186735356202021-04-15 02:14:40314.116.141.24186735356202021-04-15 05:01:40列的名称已替换,手机号码也正常显示 。
读取 csv 文件的某几列在分析数据时,有时候我们不需要采集的所有数据,只取其中需要的几列数据 。
比如上面的 csv,如果只分析 IP 地址和登录时间,读取文件时,可以只取这 2 列数据 。
# -*- coding: utf-8 -*-import pandas as pddef test():df = pd.read_csv("~/share/test.csv",skiprows=[0],usecols=[0, 2],names=["ip", "login_date"],)print(df)if __name__ == "__main__":test()通过 usecols 来指定需要那几列 。程序运行结果:
$ python test.pyiplogin_date0223.104.147.752021-04-15 01:33:081117.181.52.752021-04-15 01:48:24242.49.165.992021-04-15 02:14:40314.116.141.242021-04-15 05:01:40读取时对某些列进行转换有些列的格式,比如日期格式的列,可能在分析之前就要进行转换处理 。
上面的例子中,如果是按日分析登录情况,就不要时分秒的部分,这样我们可以在读取时就进行转换处理 。
# -*- coding: utf-8 -*-from datetime import datetimeimport pandas as pddef test():df = pd.read_csv("~/share/test.csv",skiprows=[0],usecols=[0, 2],names=["ip", "login_date"],converters={"login_date": lambda d: datetime.strptime(d, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%d")},)print(df)if __name__ == "__main__":test()通过 converters 参数转换某列 。程序运行结果:
$ python test.pyiplogin_date0223.104.147.752021-04-151117.181.52.752021-04-15242.49.165.992021-04-15314.116.141.242021-04-15数据的操作读取文件之后,得到一个 dataframe 结构,它可以当成一个矩阵来看 。
基于 dataframe,可以完成各种计算操作,pandas 提供的 API 也很多,这里只介绍我平时常用的一部分 。
分组统计之前做房价分析时,按月分析成交平均值和成交总套数时,都用到了分组统计 。
分析的第一步就是将数据分组 。
# -*- coding: utf-8 -*-import pandas as pdtest_data = https://tazarkount.com/read/{"name": ["a", "b", "c", "d"],"value": [11, 20, 31, 42],"date": ["2017", "2018", "2018", "2017"],}def main():df = pd.DataFrame(test_data)data = https://tazarkount.com/read/df.groupby("date")data = https://tazarkount.com/read/data.sum()print(data)if __name__ =="__main__":main()按照日期分组之后,运行结果如下:
$ python test2.pyvaluedate201753201851这里是求和,groupby 之后同样也可以求平均值 。
数据集变换数据集变换是用的比较多的,因为采集和分析的过程是分开的,采集的目的是数据尽量全和准确 。
所以分析之前会根据分析目的会对数据进行适当的变换 。
行操作行操作主要指从数据集中过滤出一部分数据,或者合并多个数据集 。
  1. 过滤数据
    # -*- coding: utf-8 -*-import pandas as pdtest_data = https://tazarkount.com/read/{"name": ["a", "b", "c", "d"],"value": [11, 20, 31, 42],"date": ["2017", "2018", "2018", "2017"],}def main():df = pd.DataFrame(test_data)# 选取2017年的数据data2017 = df[df["date"] == "2017"]print(data2017)# 选取value>30 的数据data30 = df[df["value"] > 30]print(data30)if __name__ == "__main__":main()运行结果如下:
    $ python test2.pynamevaluedate0a1120173d422017namevaluedate2c3120183d422017可以很方便的直接使用列名来过滤数据行
  2. 合并数据集
    # -*- coding: utf-8 -*-import pandas as pdtest_data_01 = {"name": ["a", "b", "c", "d"],"value": [11, 20, 31, 42],"date": ["2017", "2018", "2018", "2017"],}test_data_02 = {"name": ["a", "b", "c", "d"],"value": [31, 40, 51, 72],"date": ["2019", "2020", "2020", "2019"],}def main():df01 = pd.DataFrame(test_data_01)df02 = pd.DataFrame(test_data_02)# 合并数据集时,设置 ignore_index = True,可以避免index重复data = https://tazarkount.com/read/pd.concat([df01, df02], ignore_index=True)print(data)if __name__ =="__main__":main()运行结果如下:
    $ python test2.pynamevaluedate0a1120171b2020182c3120183d4220174a3120195b4020206c5120207d722019如果不设置 ignore_index = True,执行结果如下:(注意第一列有重复)
    $ python test2.pynamevaluedate0a1120171b2020182c3120183d4220170a3120191b4020202c5120203d722019
列操作列操作我用到的场景,有一个是横向统计各个列的合计和平均值 。
示例如下:
# -*- coding: utf-8 -*-import pandas as pdtest_data_01 = {"a": [11, 20],"b": [1, 2],}def main():df = pd.DataFrame(test_data_01)df["a+b"] = df["a"] + df["b"]df["(a+b)/2"] = (df["a"] + df["b"]) / 2print(df)if __name__ == "__main__":main()运行结果如下:
$ python test2.pyaba+b(a+b)/20111126.012022211.0还有就是进行数据集的列合并,比如将多个数据集的统计结果进行合并:
# -*- coding: utf-8 -*-import pandas as pdtest_data_01 = {"a": [11, 20],"b": [1, 2],}test_data_02 = {"c": [18, 50],"d": [31, 32],}def main():df01 = pd.DataFrame(test_data_01)df02 = pd.DataFrame(test_data_02)df01["a+b"] = df01["a"] + df01["b"]df01["(a+b)/2"] = (df01["a"] + df01["b"]) / 2df01 = df01.drop(columns=["a", "b"])df02["c+d"] = df02["c"] + df02["d"]df02["(c+d)/2"] = (df02["c"] + df02["d"]) / 2df02 = df02.drop(columns=["c", "d"])df = pd.concat([df01, df02], axis=1)print(df)if __name__ == "__main__":main()运行结果如下:
$ python test2.pya+b(a+b)/2c+d(c+d)/20126.04924.512211.08241.0行列互换行列互换我一般是在做动态短视频时使用的,把每个时间点一行数据(数据包含各个元素),变成每个元素在每个时间点一个数据 。
开始时,数据类似:
date,a,b2017,1,22018,2,3转换后变成:
key,date,valuea,2017,1a,2018,2b,2017,2b,2018,3转换代码:
# -*- coding: utf-8 -*-import pandas as pdtest_data = https://tazarkount.com/read/{"date": ["2017", "2018"],"a": [1, 2],"b": [2, 3],}def main():df = pd.DataFrame(test_data)print("转换前:>>>>>>")print(df)data = https://tazarkount.com/read/df.drop(columns=["date"])data = https://tazarkount.com/read/pd.melt(data)df_date = pd.concat([df["date"]] * 2, ignore_index=True)data = https://tazarkount.com/read/pd.concat([df_date, data], axis=1)print("\n转换后:>>>>>>")print(data)if __name__ == "__main__":main()运行结果如下:
$ python test2.py转换前:>>>>>>dateab02017121201823转换后:>>>>>>date variablevalue02017a112018a222017b232018b3导出数据文件导出文件很简单,只要指定个路径即可(注意,路径不存在会报错) 。
data.to_csv("./test.csv")导出时,如果不想导出每行数据的序号,加上 index=False
data.to_csv("./test.csv", index=False)如果给标题行重新命名成易懂的中文名称,设置 header 参数 。
data.to_csv("./test.csv",index=False,header=["日期","名称","时间(小时)",],)总结掌握了 pandas,感觉是多了一件随便操作数据集的利器,能够极大节省调整数据的时间 。
而且,它的处理速度极快,我在自己的笔记本电脑上处理成千上万条数据时基本都是瞬间完成,同样的数据,我用 excel 来处理,会卡顿很多 。
我的视频号:

pandas 基本操作

文章插图