Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 地理视图&x2B;投影点时,Datashader速度较慢_Python_Holoviews_Datashader_Geoviews - Fatal编程技术网

Python 地理视图&x2B;投影点时,Datashader速度较慢

Python 地理视图&x2B;投影点时,Datashader速度较慢,python,holoviews,datashader,geoviews,Python,Holoviews,Datashader,Geoviews,我正在使用datashader绘制550000000个纬度和经度。但是,为了使其有用,我需要使用geoviews覆盖贴图平铺和多边形。问题是geoviews.points()和相关的投影会导致大幅减速,这使得holoview+bokeh绘图的交互特性变得多余 下面有一个可复制的示例,但简而言之,我正在尝试使geoviews实现(3)足够快,以交互方式工作 首先设置一些数据 例如,将数据大小缩小10 uk_bounding_box = (-14.02,2.09,49.67,61.06) n = i

我正在使用
datashader
绘制550000000个纬度和经度。但是,为了使其有用,我需要使用
geoviews
覆盖贴图平铺和多边形。问题是
geoviews.points()
和相关的投影会导致大幅减速,这使得
holoview
+
bokeh
绘图的交互特性变得多余

下面有一个可复制的示例,但简而言之,我正在尝试使geoviews实现(3)足够快,以交互方式工作

首先设置一些数据 例如,将数据大小缩小10

uk_bounding_box = (-14.02,2.09,49.67,61.06)
n = int(550000000 / 10)

# Generate some fake data of the same size
df = dd.from_pandas(
    pd.DataFrame.from_dict({
        'longitude': np.random.normal(
            np.mean(uk_bounding_box[0:2]),
            np.diff(uk_bounding_box[0:2]) / 5, n
        ),
        'latitude': np.random.normal(
            np.mean(uk_bounding_box[2:4]),
            np.diff(uk_bounding_box[2:4]) / 5, n
        )
    }), npartitions=8
)

# Persist data in memory so reading wont slow down datashader
df = df.persist()
(1) 只是数据阴影 仅使用不带HoloView或geo的datashader是非常快速的-输出在4秒内渲染,包括聚合,因此如果交互,重新渲染将更快

# Set some plotting params
bounds = dict(x_range = uk_bounding_box[0:2],
              y_range = uk_bounding_box[2:4])
plot_width = 400
plot_height = 300 
纯datashader版本的时间:

%%time
cvs = ds.Canvas(plot_width=plot_width, plot_height=plot_height, **bounds)
agg = cvs.points(df, 'longitude', 'latitude', ds.count())
CPU时间:用户968毫秒,系统29.9毫秒,总计998毫秒 壁时间:506毫秒

tf.shade(agg)

(2)
datashader
holoviews
中,无
geoviews
投影 没有任何投影,这与使用纯
datashader

%%time
points = hv.Points(df, ['longitude', 'latitude']).redim.range(
    x=bounds['x_range'], y=bounds['y_range'])

shader = datashade(points, precompute=True ,**sizes).options(**opts)
CPU时间:用户3.32毫秒,系统131微秒,总计3.45毫秒 壁时间:3.47毫秒

shader

(3)
datashader
holoviews
中使用
geoviews
瓷砖、多边形和投影 这里是问题的症结所在-我想将datashader层与一些地图分幅和地理空间多边形对齐。这导致了一个巨大的减速,对于我正在处理的数据的大小来说,这使得交互式可视化变得多余。(渲染的总等待时间为12分钟)

我确信这与投影点相关的开销有关-有没有办法避免这种情况或任何其他解决方法,如预计算投影

# Grab an example shape file to work with
ne_path = gpd.datasets.get_path('naturalearth_lowres')
example_shapes_df = gpd.read_file(ne_path)
uk_shape = example_shapes_df[example_shapes_df.name.str.contains('United K')]


# Grab maptiles
map_tiles = gv.tile_sources.ESRI

# In actual workflow I need to add some polygons
polys = gv.Polygons(uk_shape)
如上所述,添加了
gv.points()
和投影

%%time 
points = gv.Points(df, ['longitude', 'latitude']).redim.range(
    x=bounds['x_range'], y=bounds['y_range'])

projected = gv.operation.project_points(points)

shader = datashade(projected, precompute=True ,**sizes).options(**opts)
CPU时间:用户11.8秒,系统3.16秒,总计15秒 壁时间:12.5秒

shader * map_tiles * polys

根据@philippjfr的建议,解决方案是将坐标投影到适当的坐标系中,并使用上述方法2或3进行渲染

大概是这样的:

import cartopy

def platcaree_to_mercator_vectorised(x, y):
    '''Use cartopy to convert Platecarree coords to Mercator.'''
    return(cartopy.crs.GOOGLE_MERCATOR.transform_points(
        cartopy.crs.PlateCarree(), x, y))

def platcaree_for_map_partitions(pddf):
    '''Wrapper to apply mercator conversion and convert back to dataframe for Dask.'''
    as_arrays = platcaree_to_mercator_vectorised(pddf.longitude.values,pddf.latitude.values)
    as_df = pd.DataFrame.from_records(as_arrays[:, :2], columns=['longitude', 'latitude'])
    return(as_df)


# Project the points
df_projected = df.map_partitions(platcaree_for_map_partitions,
                                 meta={'longitude': 'f8', 'latitude': 'f8'})
from dask.diagnostics import ProgressBar
with ProgressBar():
    df_projected.to_parquet('abb_projected.parquet', compression='SNAPPY')

然后将此投影数据集与方法2或3一起使用,详细说明见上文

你能澄清一下时间安排吗?您说需要12分钟,但%%time输出表示12秒,在本地运行示例时,投影大约需要30秒,渲染大约需要1.5秒,缩放更新大约需要300毫秒。Hi@philippjfr-在实际代码中,数据是示例大小的10倍
n=int(550000000/10)
我在这里对其进行了缩放,因此运行该示例不需要太长时间,但当我使用完整的550000000坐标时,最终的绘图需要12分钟。这是实际数据的每次时间,与上面的代码相同,但对于550000,00点:1)
CPU时间:用户8.4秒,系统:16.1秒,总计:24.4秒壁时间:4.38秒
2)
CPU时间:用户3.9毫秒,系统476微秒,总计:4.38毫秒壁时间:4.35毫秒
3)
CPU时间:用户3分钟24秒,系统6分钟27秒,总计:9分钟51s墙时间:10分钟31s
查看剖面图,似乎投影占用了大部分时间:``ncalls tottime percall cumtime percall filename:lineno(函数)1268.726 268.726 268.726 268.726{cartopy.\u crs.crs'对象的方法“变换点”}191.124 191.124 625.980 625.980 projection.py:188(_process_element)8127.947 15.993 127.947 15.993{内置方法numpy.core.multiarray.concatenate}1 34.910 34.910 34.910 34.910 34.910 projection.py:195()1 2.001 627.981 627.981维。py:712(map)``谢谢,我应该仔细阅读。我们计划最终将投影代码与dask并行,但目前我只能建议您投影一次点,然后将投影点保存为拼花地板文件;GeoViews不会不必要地重新投影数据。因此,在投影之后,您不必避免地理视图,您只是不需要它。
shader * map_tiles * polys
import cartopy

def platcaree_to_mercator_vectorised(x, y):
    '''Use cartopy to convert Platecarree coords to Mercator.'''
    return(cartopy.crs.GOOGLE_MERCATOR.transform_points(
        cartopy.crs.PlateCarree(), x, y))

def platcaree_for_map_partitions(pddf):
    '''Wrapper to apply mercator conversion and convert back to dataframe for Dask.'''
    as_arrays = platcaree_to_mercator_vectorised(pddf.longitude.values,pddf.latitude.values)
    as_df = pd.DataFrame.from_records(as_arrays[:, :2], columns=['longitude', 'latitude'])
    return(as_df)


# Project the points
df_projected = df.map_partitions(platcaree_for_map_partitions,
                                 meta={'longitude': 'f8', 'latitude': 'f8'})
from dask.diagnostics import ProgressBar
with ProgressBar():
    df_projected.to_parquet('abb_projected.parquet', compression='SNAPPY')