Python:计算平均纬度,包括日期变更线
Python: Calculation of mean latitude including dateline crosses
我有一个 [-180, 180] 范围内的经度值数组 (lons)。我需要找到时间序列的平均值。这很容易用
完成
np.mean(lons)
如果系列包含日期线任一侧的值,那么这个直接的意思当然不起作用。计算所有可能情况的平均值的正确方法是什么?请注意,我宁愿没有以不同方式处理日期变更线案例的条件。
我在从度数转换为弧度后玩过 np.unwrap,但我知道我的计算是错误的,因为一小部分情况给我的平均经度接近 0 度(子午线)非洲。这些是不可能的,因为这是一个海洋数据集。
谢谢。
编辑:我现在意识到计算时间序列的平均 [lat, lon] 位置的更精确的方法可能是转换为笛卡尔网格。我可能会走这条路。
这是 directional statistics, where the angular mean is computed in the complex plane (see this section) 的应用程序。结果是一个复数,其虚部代表平均角度:
import numpy as np
def angular_mean(angles_deg):
N = len(angles_deg)
mean_c = 1.0 / N * np.sum(np.exp(1j * angles_deg * np.pi/180.0))
return np.angle(mean_c, deg=True)
lons = [
np.array([-175, -170, 170, 175]), # broad distribution
np.random.rand(1000) # narrow distribution
]
for lon in lons:
print angular_mean(lon), np.mean(lon)
如您所见,算术平均值和 angular 平均值对于窄分布非常相似,而对于广泛分布则有显着差异。
使用笛卡尔坐标是不合适的,因为质心将位于地球内,但由于您使用的是表面数据,我假设您希望它位于表面上。
这是我的解决方案。请注意,我计算了平均纬度和经度,还计算了计算出的平均纬度 (lat_mean) 和平均经度 (lon_mean 的 [lat, lon] 坐标的平均距离 (mean_dist) ]).原因是我也对中央 [lat, lon] 的变化有多大感兴趣。我相信这是正确的,但我愿意讨论!
lat_size = np.size(lats)
lon_rad = np.deg2rad(lons) # lons in degrees [-180, 180]
lat_rad = np.deg2rad(lats) # lats in degrees [-90, 90]
R = 6371 # Approx radius of Earth (km)
x = R * np.cos(lat_rad) * np.cos(lon_rad)
y = R * np.cos(lat_rad) * np.sin(lon_rad)
z = R * np.sin(lat_rad)
x_mean = np.mean(x)
y_mean = np.mean(y)
z_mean = np.mean(z)
lat_mean = np.rad2deg(np.arcsin(z_mean / R))
lon_mean = np.rad2deg(np.arctan2(y_mean, x_mean))
# Calculate distance from centre point for each [lat, lon] pair
dist_list = np.empty(lat_size)
dist_list.fill(np.nan)
p = 0
for lat, lon in zip(lats, lons):
coords_1 = (lat, lon)
coords_2 = (lat_mean, lon_mean )
dist_list[p] = geopy.distance.vincenty(coords_1, coords_2).km
p = p + 1
mean_dist = np.mean(dist_list)
return lat_mean, lon_mean, mean_dist
我有一个 [-180, 180] 范围内的经度值数组 (lons)。我需要找到时间序列的平均值。这很容易用
完成np.mean(lons)
如果系列包含日期线任一侧的值,那么这个直接的意思当然不起作用。计算所有可能情况的平均值的正确方法是什么?请注意,我宁愿没有以不同方式处理日期变更线案例的条件。
我在从度数转换为弧度后玩过 np.unwrap,但我知道我的计算是错误的,因为一小部分情况给我的平均经度接近 0 度(子午线)非洲。这些是不可能的,因为这是一个海洋数据集。
谢谢。
编辑:我现在意识到计算时间序列的平均 [lat, lon] 位置的更精确的方法可能是转换为笛卡尔网格。我可能会走这条路。
这是 directional statistics, where the angular mean is computed in the complex plane (see this section) 的应用程序。结果是一个复数,其虚部代表平均角度:
import numpy as np
def angular_mean(angles_deg):
N = len(angles_deg)
mean_c = 1.0 / N * np.sum(np.exp(1j * angles_deg * np.pi/180.0))
return np.angle(mean_c, deg=True)
lons = [
np.array([-175, -170, 170, 175]), # broad distribution
np.random.rand(1000) # narrow distribution
]
for lon in lons:
print angular_mean(lon), np.mean(lon)
如您所见,算术平均值和 angular 平均值对于窄分布非常相似,而对于广泛分布则有显着差异。
使用笛卡尔坐标是不合适的,因为质心将位于地球内,但由于您使用的是表面数据,我假设您希望它位于表面上。
这是我的解决方案。请注意,我计算了平均纬度和经度,还计算了计算出的平均纬度 (lat_mean) 和平均经度 (lon_mean 的 [lat, lon] 坐标的平均距离 (mean_dist) ]).原因是我也对中央 [lat, lon] 的变化有多大感兴趣。我相信这是正确的,但我愿意讨论!
lat_size = np.size(lats)
lon_rad = np.deg2rad(lons) # lons in degrees [-180, 180]
lat_rad = np.deg2rad(lats) # lats in degrees [-90, 90]
R = 6371 # Approx radius of Earth (km)
x = R * np.cos(lat_rad) * np.cos(lon_rad)
y = R * np.cos(lat_rad) * np.sin(lon_rad)
z = R * np.sin(lat_rad)
x_mean = np.mean(x)
y_mean = np.mean(y)
z_mean = np.mean(z)
lat_mean = np.rad2deg(np.arcsin(z_mean / R))
lon_mean = np.rad2deg(np.arctan2(y_mean, x_mean))
# Calculate distance from centre point for each [lat, lon] pair
dist_list = np.empty(lat_size)
dist_list.fill(np.nan)
p = 0
for lat, lon in zip(lats, lons):
coords_1 = (lat, lon)
coords_2 = (lat_mean, lon_mean )
dist_list[p] = geopy.distance.vincenty(coords_1, coords_2).km
p = p + 1
mean_dist = np.mean(dist_list)
return lat_mean, lon_mean, mean_dist