Тепловая карта на Zeppelin с использованием листовки

#r #leaflet #sparkr #apache-zeppelin

#r #листовка #sparkr #apache-zeppelin

Вопрос:

Я хочу добавить тепловую карту в абзац Zeppelin, используя листовку с R. Я написал скрипт в R Studio, который работает нормально, но при переходе на Zeppelin тепловая карта не отображается. Вот мой код в R Studio

 map3 <- Leaflet$new()
map3$setView(c(29.7632836,  -95.3632715), 10)

vector <- c( list(c(29.76,-95.36, 50)), list(c(29.77, -95.37, 50)), list(c(29.75,-95.39,50)))
#vector = toJSONArray2(na.omit(vector), json = F, names = F)
cat(rjson::toJSON(vector[1:3]))

map3$addAssets(jshead = c(
  "http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"
))

map3$addAssets(jshead = c("http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"))
map3$setTemplate(afterScript = sprintf("
    <script>
      var addressPoints = %s
      var heat = L.heatLayer(addressPoints).addTo(map)           
    </script>"
                                       ,rjson::toJSON(vector)))

map3
  

Мой код в Zeppelin почти идентичен. Изменяется только метод ввода и вывода:

 library(SparkR)

sparkcontext <- sparkR.init("local[4]","cvspark",sparkEnvir=list(spark.executor.memory="1g"))

#sparkR.session()
positions <- sql("SELECT lat, long FROM my_table")
pos <- collect(positions)

map3 <- Leaflet$new()

map3$setView(c(39.93, 32.85))

vector <- c()
values1 <- pos[[1]]
values2 <- pos[[2]]
for (i in 1:length(values1))
  vector <- c(vector, list(c(values1[i], values2[i], 1000)))

cat(rjson::toJSON(vector[1:3]))

map3$addAssets(jshead = c("http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"))
map3$setTemplate(afterScript = sprintf("
    <script>
      var addressPoints = %s
      var heat = L.heatLayer(addressPoints).addTo(map)           
    </script>"
    ,rjson::toJSON(vector)))


map3$print("map3", include_assets=TRUE, cdn=TRUE)
  

Следующий код показывает, что входные данные идентичны:

 cat(rjson::toJSON(vector[1:3]))
  

Вывод R Studio:

 [[29.76,-95.36,50],[29.77,-95.37,50],[29.75,-95.39,50]],
  

Вывод Zeppelin:

 [[41.6406843380063,37.6892873258843,1000],[37.0194101218466,30.3908073266391,1000],[34.0236444385`445,40.5599139822316,1000]]
  

Проблема здесь map3$print("map3", include_assets=TRUE, cdn=TRUE) в том, что слой тепловой карты не включается в его вывод. Насколько я знаю, для отображения карты на Zeppelin необходимо вызвать этот метод. Вопрос в том, как нам заставить метод печати включать код javascript, который включает слой тепловой карты на карте.

Также я получаю следующую ошибку в Zeppelin. Но я не думаю, что это имеет отношение к этому вопросу:

 Error in sparkR.sparkContext(master, appName, sparkHome, convert`NamedListToEnv(sparkEnvir), : JVM is not ready after 10 seconds
  

Комментарии:

1. Кроме того, код в Zeppelin занимает слишком много времени для подключения к Spark, это еще одна проблема.

Ответ №1:

Этот код не будет отображать слой тепловой карты:

 map3$print("map3", include_assets=TRUE, cdn=TRUE)
  

Вместо этого используйте интерпретатор %angular и привязку переменных:

 %angular
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.5/leaflet.css" />
<script src="scripts/leaflet-heat.js"></script>

<input type="hidden" value="{{coordinates}}" id="coordinates_values">
<div id="map" style="height: 800px; width: 100%"></div>
<script type="text/javascript">
function initMap() {
    var map = L.map('map').setView([39.95, 32.50], 10);

    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data amp;copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
        maxZoom: 12,
        minZoom: 3
    }).addTo(map);

    var geoMarkers = L.layerGroup().addTo(map);

    var el = angular.element($('#map').parent('.ng-scope'));

    console.log( $("#coordinates_values").val())
    var coordinates = $.parseJSON( $("#coordinates_values").val() );
    var heat = L.heatLayer( coordinates, {radius: 35}).addTo(map);

    angular.element(el).ready(function() {
        window.locationWatcher = el.scope().compiledScope.$watch('locations', function(newValue, oldValue) {
            // geoMarkers.clearLayers(); -- if you want to only show new data clear the layer first
            angular.forEach(newValue, function(tweet) {
                var marker = L.marker([ tweet.loc.lat, tweet.loc.lon ])
                  .bindPopup(tweet.user   ": "   tweet.tweet)
                  .addTo(geoMarkers);
            });
        })
    });
}

if (window.locationWatcher) {
    // clear existing watcher otherwise we'll have duplicates
    window.locationWatcher();
}

// ensure we only load the script once, seems to cause issues otherwise
if (window.L) {
    $("#coordinates_values").ready(function(){
        initMap();
    });
} else {
    console.log('Loading Leaflet library');
    var sc = document.createElement('script');
    sc.type = 'text/javascript';
    sc.src = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.5/leaflet.js';
    sc.onload = initMap;
    sc.onerror = function(err) { alert(err); }
    document.getElementsByTagName('head')[0].appendChild(sc);
}
</script>