概述
python 的 pandas 库用来处理表格类型(也就是矩阵)的数据非常方便, 这个库用来在可视化之前对数据进行变换,计算和汇总之类的操作再好不过。
下面整理了最近我在做数据分析的短视频时常用的一些方法。
读取数据文件
做视频之前,我采集的数据都是用 csv 格式保存的,这里主要演示 pandas 库的 read_csv 方法。
读取其他文件格式的方式类似,主要是函数名称不同,参数都差不多。
读取 csv 文件
读取 csv 文件非常简单,指定 csv 文件的路径即可。 测试用 csv 文件内容如下:
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 pd
def test():
df = pd.read_csv(
\"~/share/test.csv\",
)
print(df)
if __name__ == \"__main__\":
test()
程序运行结果:
$ python test.py
IP地址 手机号码 登录日期
0 223.104.147.75 1.995176e+10 2021-04-15 01:33:08
1 117.181.52.75 1.587357e+10 2021-04-15 01:48:24
2 42.49.165.99 1.867354e+10 2021-04-15 02:14:40
3 14.116.141.24 1.867354e+10 2021-04-15 05:01:40
读取之后修改列的名称,指定列的类型
csv 文件中的列名有时候没有,或者有时候是中文的,列名是后续进行操作数据时使用的 key,一般在读取时将其转换成英文。
同时,可以看出手机号码默认被当成数值类型了,所以用科技计数法来表示,在读取数据时,可以设置此列为字符串类型。
# -*- coding: utf-8 -*-
import pandas as pd
def test():
df = pd.read_csv(
\"~/share/test.csv\",
skiprows=[0],
names=[\"ip\", \"mobile\", \"login_date\"],
dtype={\"mobile\": str},
)
print(df)
if __name__ == \"__main__\":
test()
程序运行结果:
$ python test.py
ip mobile login_date
0 223.104.147.75 19951762925 2021-04-15 01:33:08
1 117.181.52.75 15873565020 2021-04-15 01:48:24
2 42.49.165.99 18673535620 2021-04-15 02:14:40
3 14.116.141.24 18673535620 2021-04-15 05:01:40
列的名称已替换,手机号码也正常显示。
读取 csv 文件的某几列
在分析数据时,有时候我们不需要采集的所有数据,只取其中需要的几列数据。
比如上面的 csv,如果只分析 IP 地址和登录时间,读取文件时,可以只取这 2 列数据。
# -*- coding: utf-8 -*-
import pandas as pd
def 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.py
ip login_date
0 223.104.147.75 2021-04-15 01:33:08
1 117.181.52.75 2021-04-15 01:48:24
2 42.49.165.99 2021-04-15 02:14:40
3 14.116.141.24 2021-04-15 05:01:40
读取时对某些列进行转换
有些列的格式,比如日期格式的列,可能在分析之前就要进行转换处理。
上面的例子中,如果是按日分析登录情况,就不要时分秒的部分,这样我们可以在读取时就进行转换处理。
# -*- coding: utf-8 -*-
from datetime import datetime
import pandas as pd
def 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.py
ip login_date
0 223.104.147.75 2021-04-15
1 117.181.52.75 2021-04-15
2 42.49.165.99 2021-04-15
3 14.116.141.24 2021-04-15
数据的操作
读取文件之后,得到一个 dataframe 结构,它可以当成一个矩阵来看。
基于 dataframe,可以完成各种计算操作,pandas 提供的 API 也很多,这里只介绍我平时常用的一部分。
分组统计
之前做房价分析时,按月分析成交平均值和成交总套数时,都用到了分组统计。
分析的第一步就是将数据分组。
# -*- coding: utf-8 -*-
import pandas as pd
test_data = {
\"name\": [\"a\", \"b\", \"c\", \"d\"],
\"value\": [11, 20, 31, 42],
\"date\": [\"2017\", \"2018\", \"2018\", \"2017\"],
}
def main():
df = pd.DataFrame(test_data)
data = df.groupby(\"date\")
data = data.sum()
print(data)
if __name__ == \"__main__\":
main()
按照日期分组之后,运行结果如下:
$ python test2.py
value
date
2017 53
2018 51
这里是求和,groupby 之后同样也可以求平均值。
数据集变换
数据集变换是用的比较多的,因为采集和分析的过程是分开的,采集的目的是数据尽量全和准确。
所以分析之前会根据分析目的会对数据进行适当的变换。
行操作
行操作主要指从数据集中过滤出一部分数据,或者合并多个数据集。
过滤数据
# -*- coding: utf-8 -*-
import pandas as pd
test_data = {
\"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.py
name value date
0 a 11 2017
3 d 42 2017
name value date
2 c 31 2018
3 d 42 2017
可以很方便的直接使用列名来过滤数据行
合并数据集
# -*- coding: utf-8 -*-
import pandas as pd
test_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 = pd.concat([df01, df02], ignore_index=True)
print(data)
if __name__ == \"__main__\":
main()
运行结果如下:
$ python test2.py
name value date
0 a 11 2017
1 b 20 2018
2 c 31 2018
3 d 42 2017
4 a 31 2019
5 b 40 2020
6 c 51 2020
7 d 72 2019
如果不设置 ignore_index = True,执行结果如下:(注意第一列有重复)
$ python test2.py
name value date
0 a 11 2017
1 b 20 2018
2 c 31 2018
3 d 42 2017
0 a 31 2019
1 b 40 2020
2 c 51 2020
3 d 72 2019
列操作
列操作我用到的场景,有一个是横向统计各个列的合计和平均值。
示例如下:
# -*- coding: utf-8 -*-
import pandas as pd
test_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\"]) / 2
print(df)
if __name__ == \"__main__\":
main()
运行结果如下:
$ python test2.py
a b a+b (a+b)/2
0 11 1 12 6.0
1 20 2 22 11.0
还有就是进行数据集的列合并,比如将多个数据集的统计结果进行合并:
# -*- coding: utf-8 -*-
import pandas as pd
test_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\"]) / 2
df01 = df01.drop(columns=[\"a\", \"b\"])
df02[\"c+d\"] = df02[\"c\"] + df02[\"d\"]
df02[\"(c+d)/2\"] = (df02[\"c\"] + df02[\"d\"]) / 2
df02 = df02.drop(columns=[\"c\", \"d\"])
df = pd.concat([df01, df02], axis=1)
print(df)
if __name__ == \"__main__\":
main()
运行结果如下:
$ python test2.py
a+b (a+b)/2 c+d (c+d)/2
0 12 6.0 49 24.5
1 22 11.0 82 41.0
行列互换
行列互换我一般是在做动态短视频时使用的,把每个时间点一行数据(数据包含各个元素),变成每个元素在每个时间点一个数据。
开始时,数据类似:
date,a,b
2017,1,2
2018,2,3
转换后变成:
key,date,value
a,2017,1
a,2018,2
b,2017,2
b,2018,3
转换代码:
# -*- coding: utf-8 -*-
import pandas as pd
test_data = {
\"date\": [\"2017\", \"2018\"],
\"a\": [1, 2],
\"b\": [2, 3],
}
def main():
df = pd.DataFrame(test_data)
print(\"转换前:>>>>>>\")
print(df)
data = df.drop(columns=[\"date\"])
data = pd.melt(data)
df_date = pd.concat([df[\"date\"]] * 2, ignore_index=True)
data = pd.concat([df_date, data], axis=1)
print(\"\\n转换后:>>>>>>\")
print(data)
if __name__ == \"__main__\":
main()
运行结果如下:
$ python test2.py
转换前:>>>>>>
date a b
0 2017 1 2
1 2018 2 3
转换后:>>>>>>
date variable value
0 2017 a 1
1 2018 a 2
2 2017 b 2
3 2018 b 3
导出数据文件
导出文件很简单,只要指定个路径即可(注意,路径不存在会报错)。
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 来处理,会卡顿很多。
我的视频号:
来源:https://www.cnblogs.com/wang_yb/p/14706022.html
图文来源于网络,如有侵权请联系删除。