-
题目:csv文件为纽约市出租车的出行数据,数据包括上/下车的位置坐标,上/下车的人数。研究区域范围如图 1所示,其左上角坐标为(0,1),右下角坐标为(1,0)。
图1
要求:将研究区域划分为32*32的网格,按从左到右、从上到下对网格进行编号(1~1024),并分别求出每个网格的上/下车的人数,数据保存格式如表 1所示,保存为csv文件。
表1
- 首先,读取数据,查看数据有哪些,生成描述性统计,同时查看是否有缺失值。
import pandas as pd
import matplotlib.pyplot as plt
file_name = 'nyc_taxi_data.csv'
data_pd = pd.read_csv(file_name)
print(data_pd.head())
print(data_pd.shape)
print(data_pd.isnull().sum())
运行结果如图2所示:
图2
从结果可以看出数据大概有一千万行,共有5列,分别为 passengers、up_y、up_x、off_y、off_x,同时数据中没有缺失值。
- 先将数据可视化,观察上下车地点。
fig = plt.figure(figsize=(20,10))
alpha = 0.05
ax1 = fig.add_subplot(121)
plt.scatter(up_x, up_y, c='green', marker='.', alpha=alpha)
ax1.set_title('up location')
ax2 = fig.add_subplot(122)
plt.scatter(off_x, off_y, c='red', marker='.', alpha=alpha)
ax2.set_title('off location')
plt.show()
运行结果如图3所示:
图3
从图中能够看出上下车的分布情况,其中左边是上车的地点,右边为下车的地点。
- 思路:先初始化三个32*32的零矩阵,里面分别存放1024个区域的索引、每个区域的上车人数和下车人数。
up_passengers = np.zeros((32,32))
off_passengers = np.zeros((32,32))
grid_index = np.zeros(32*32)
- 将1024个区域建立索引
for i in range(32*32):
grid_index[i] = i+1
- 然后向1024各区域中添加元素,由于索引方式是从左到右、从上到下。所以先确定点在哪个区域内,再将属于该区域的点添加到索引中去,最后将索引区域内的人数进行统计。
length = len(data_pd)
for i in trange(length):
up_passengers[int((1-up_y[i])*32), int(up_x[i]*32)] += passengers[i]
off_passengers[int((1-off_y[i])*32), int(off_x[i]*32)] += passengers[i]
其中,[int((1-up_y[i])32), int(up_x[i]32)]是区域的索引,每个区域的刻度为1/32,y值从1到0,x值从0到1。因为索引为整数,所以需要用到int()函数,将值转换为整数。右边的式子是将属于该区域的passengers人数添加到矩阵中。这里用的是 trange而不是range,是因为trange可以看到进度条。
注意:这里面涉及到数据的遍历,pandas数据遍历有这几种方式:for…in循环迭代方式、iterrows()生成器方式、apply()方法循环方式、Pandas series 的矢量化方式、Numpy arrays的矢量化方式。其中最后一种方式速度最快,所以需要将数据进行一下处理。
up_y = data_pd.up_y.values
up_x = data_pd.up_x.values
off_y = data_pd.off_y.values
off_x = data_pd.off_x.values
passengers = data_pd.passengers.values
实测Pandas series 的矢量化方式需要10分钟左右,而Numpy arrays的矢量化方式只需要50秒左右,大大提高了速度。
- 接下来将数据转进行保存,这里的range函数全部改为trange。
up_passengers = up_passengers.reshape(-1)
off_passengers = off_passengers.reshape(-1)
data_all = np.zeros((1024,3))
for i in trange(1024):
data_all[i,0] = grid_index[i]
data_all[i,1] = up_passengers[i]
data_all[i,2] = off_passengers[i]
data = pd.DataFrame(data_all, columns=["grid_index", "up_passengers",
"off_passengers"])
data.to_csv("nyc_taxi_grid_data.csv", index=False)
return data_all
到这里,程序就完成了。当然,这里还有其他方式保存数据,比如采取字典的形式,将索引设置为key,上下车人数为value。还有,数据量达到了300M可以通过优化内存的方式来减少内存的使用,提高数据的读取效率。
网友评论