1

アニメーション化されたコロプレスを構築するために、rmaps [ https://github.com/ramnathv/rMaps/blob/master/R/Datamaps.R#L43]でイコロプレス関数を使用しています。年単位ではなく、月単位でアニメートしたい。これを実現するために、コード内の年という用語のすべてのインスタンスを月に変更しました。最初の月のデータが表示されますが、アニメーションは再生されません。コードの変更が正しければ、問題の要因として月が含まれている可能性があると思われますが、正しい形式を維持しながら数値または日付に変換できません。誰でも解決策を提供できますか? 私のデータのサンプルは以下のとおりです

structure(list(month = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("2013-03", 
"2013-04", "2013-05", "2013-06", "2013-07", "2013-08", "2013-09", 
"2013-10", "2013-11", "2013-12", "2014-01", "2014-02", "2014-03", 
"2014-04", "2014-05", "2014-06", "2014-07", "2014-08"), class = "factor"), 
iso = structure(c(2L, 5L, 6L, 7L, 8L, 15L), .Label = c("ABW", 
"AFG", "AGO", "AIA", "ALB", "ARE", "ARG", "AUS", "AUT", "AZE", 
"BEL", "BEN", "BFA", "BGD", "BGR", "BHR", "BHS", "BIH", "BLR", 
"BLZ", "BMU", "BRA", "BRB", "BWA", "CAF", "CAN", "CHE", "CHL", 
"CHN", "CMR", "COL", "COM", "CRI", "CUB", "CYM", "CYP", "CZE", 
"DEU", "DJI", "DMA", "DNK", "DOM", "DZA", "ECU", "EGY", "ERI", 
"ESP", "EST", "ETH", "FIN", "FJI", "FRA", "FRO", "GAB", "GBR", 
"GEO", "GGY", "GHA", "GIB", "GIN", "GLP", "GMB", "GNQ", "GRC", 
"GRD", "GTM", "GUF", "GUM", "GUY", "HKG", "HND", "HRV", "HTI", 
"HUN", "IDN", "IMN", "IND", "IRL", "IRQ", "ISL", "ISR", "ITA", 
"JAM", "JEY", "JOR", "JPN", "KAZ", "KEN", "KGZ", "KHM", "KWT", 
"LBN", "LBR", "LBY", "LCA", "LKA", "LSO", "LTU", "LUX", "LVA", 
"MAR", "MCO", "MDV", "MEX", "MLI", "MLT", "MMR", "MNG", "MOZ", 
"MRT", "MUS", "MWI", "MYS", "NAM", "NCL", "NER", "NGA", "NIC", 
"NLD", "NOR", "NPL", "NZL", "OMN", "PAK", "PAN", "PER", "PHL", 
"PNG", "POL", "PRI", "PRT", "PRY", "QAT", "ROU", "RWA", "SAU", 
"SDN", "SEN", "SGP", "SLB", "SLE", "SLV", "SOM", "SRB", "SSD", 
"SUR", "SVK", "SVN", "SWE", "SYC", "TGO", "THA", "TJK", "TKM", 
"TON", "TTO", "TUN", "TUR", "UGA", "UKR", "URY", "USA", "UZB", 
"VNM", "VUT", "WSM", "YEM", "ZAF", "ZMB", "ZWE"), class = "factor"), 
volume = c(1L, 1L, 5L, 4L, 12L, 10L)), .Names = c("month", 
"iso", "volume"), row.names = c(NA, 6L), class = "data.frame")

コード:

Mchoropleth <- function(x, data, pal = "Blues", ncuts = 5, animate = NULL, play = F, map = 
 'world', legend = TRUE, labels = TRUE, ...){
d <- Datamaps$new()
fml = lattice::latticeParseFormula(x, data = data)
data = transform(data, 
fillKey = cut(
  fml$left, 
  unique(quantile(fml$left, seq(0, 1, 1/ncuts))),
  ordered_result = TRUE
 )
)
fillColors = RColorBrewer::brewer.pal(ncuts, pal)
d$set(
scope = map, 
fills = as.list(setNames(fillColors, levels(data$fillKey))), 
legend = legend,
labels = labels,
...
)
if (!is.null(animate)){
range_ = summary(data[[animate]])
data = dlply(data, animate, function(x){
  y = toJSONArray2(x, json = F)
  names(y) = lapply(y, '[[', fml$right.name)
  return(y)
 })
 d$set(
  bodyattrs = "ng-app ng-controller='rChartsCtrl'"  
)
d$addAssets(
  jshead = "http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"
)
if (play == T){
  d$setTemplate(chartDiv = sprintf("
    <div class='container'>
     <button ng-click='animateMap()'>Play</button>
     <div id='{{chartId}}' class='rChart datamaps'></div>  
    </div>
    <script>
      function rChartsCtrl($scope, $timeout){
        $scope.month = %s;
          $scope.animateMap = function(){
          if ($scope.month > %s){
            return;
          }
          map{{chartId}}.updateChoropleth(chartParams.newData[$scope.month]);
          $scope.month += 1
          $timeout($scope.animateMap, 1000)
        }
      }
   </script>", range_[1], range_[6])
  )

} else {
  d$setTemplate(chartDiv = sprintf("
    <div class='container'>
      <input id='slider' type='range' min=%s max=%s ng-model='value' width=200>
      <div id='{{chartId}}' class='rChart datamaps'></div>  
    </div>
    <script>
      function rChartsCtrl($scope){
        $scope.month = %s;
        $scope.$watch('month', function(newMonth){
          map{{chartId}}.updateChoropleth(chartParams.newData[newMonth]);
        })
      }
   </script>", range_[1], range_[6], range_[1])
  )
}
d$set(newData = data, data = data[[1]])

} else {
d$set(data = dlply(data, fml$right.name))
}
return(d)
}
4

1 に答える 1

4

上記の質問からのビットを含む、完全に再現可能なコード サンプルを作成しようとします。

まず、指定したとおりにデータを設定します。

dt <- structure(list(month = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("2013-03", 
"2013-04", "2013-05", "2013-06", "2013-07", "2013-08", "2013-09", 
"2013-10", "2013-11", "2013-12", "2014-01", "2014-02", "2014-03", 
"2014-04", "2014-05", "2014-06", "2014-07", "2014-08"), class = "factor"), 
iso = structure(c(2L, 5L, 6L, 7L, 8L, 15L), .Label = c("ABW", 
"AFG", "AGO", "AIA", "ALB", "ARE", "ARG", "AUS", "AUT", "AZE", 
"BEL", "BEN", "BFA", "BGD", "BGR", "BHR", "BHS", "BIH", "BLR", 
"BLZ", "BMU", "BRA", "BRB", "BWA", "CAF", "CAN", "CHE", "CHL", 
"CHN", "CMR", "COL", "COM", "CRI", "CUB", "CYM", "CYP", "CZE", 
"DEU", "DJI", "DMA", "DNK", "DOM", "DZA", "ECU", "EGY", "ERI", 
"ESP", "EST", "ETH", "FIN", "FJI", "FRA", "FRO", "GAB", "GBR", 
"GEO", "GGY", "GHA", "GIB", "GIN", "GLP", "GMB", "GNQ", "GRC", 
"GRD", "GTM", "GUF", "GUM", "GUY", "HKG", "HND", "HRV", "HTI", 
"HUN", "IDN", "IMN", "IND", "IRL", "IRQ", "ISL", "ISR", "ITA", 
"JAM", "JEY", "JOR", "JPN", "KAZ", "KEN", "KGZ", "KHM", "KWT", 
"LBN", "LBR", "LBY", "LCA", "LKA", "LSO", "LTU", "LUX", "LVA", 
"MAR", "MCO", "MDV", "MEX", "MLI", "MLT", "MMR", "MNG", "MOZ", 
"MRT", "MUS", "MWI", "MYS", "NAM", "NCL", "NER", "NGA", "NIC", 
"NLD", "NOR", "NPL", "NZL", "OMN", "PAK", "PAN", "PER", "PHL", 
"PNG", "POL", "PRI", "PRT", "PRY", "QAT", "ROU", "RWA", "SAU", 
"SDN", "SEN", "SGP", "SLB", "SLE", "SLV", "SOM", "SRB", "SSD", 
"SUR", "SVK", "SVN", "SWE", "SYC", "TGO", "THA", "TJK", "TKM", 
"TON", "TTO", "TUN", "TUR", "UGA", "UKR", "URY", "USA", "UZB", 
"VNM", "VUT", "WSM", "YEM", "ZAF", "ZMB", "ZWE"), class = "factor"), 
volume = c(1L, 1L, 5L, 4L, 12L, 10L)), .Names = c("month", 
"iso", "volume"), row.names = c(NA, 6L), class = "data.frame")

このデータには、すべて同じ月の 6 行しか含まれていないため、iso(ISO 国コード) とmonth. 私はそれを呼びますdt2。今後の参考のために、使用可能なデータを提供することは非常に役立ちます。

  dt2 <- data.frame(
    iso = as.factor(rep(levels(dt$iso),length(levels(dt$month))))
    ,month = unlist(lapply(1:length(levels(dt$month)),function(m){
      rep(levels(dt$month)[m],length(levels(dt$iso)))
    }))
    ,volume = runif(length(levels(dt$month))*length(levels(dt$iso)),0,100)
  )

必要に応じfactorsてお知らせください。ただし、一般的にandまたはを使用する場合は、因子をnumericorcharacter値に変換するのが賢明です。rChartsrMapsJSON

  # no reason to have factors
  # so I suggest converting to character
  dt2$iso <- as.character(dt2$iso)
  dt2$month <- as.character(dt2$month)

問題が要因の使用に起因するという点であなたは正しいですが、より具体的には、ichorolpleth関数は文字ではなく数字を期待しています。問題を修正する方法は複数あります。このルートを選んだ

  Mchoropleth <- function(x, data, pal = "Blues", ncuts = 5, animate = NULL, play = F, map = 
   'world', legend = TRUE, labels = TRUE, ...){
    d <- Datamaps$new()
    fml = lattice::latticeParseFormula(x, data = data)
    data = transform(data, 
    fillKey = cut(
      fml$left, 
      unique(quantile(fml$left, seq(0, 1, 1/ncuts))),
      ordered_result = TRUE
     )
    )
    fillColors = RColorBrewer::brewer.pal(ncuts, pal)
    d$set(
    scope = map, 
    fills = as.list(setNames(fillColors, levels(data$fillKey))), 
    legend = legend,
    labels = labels,
    ...
    )
    if (!is.null(animate)){

    range_ = sort(unique(data[[animate]]))


    data = dlply(data, animate, function(x){
      y = toJSONArray2(x, json = F)
      names(y) = lapply(y, '[[', fml$right.name)
      return(y)
     })
     d$set(
      bodyattrs = "ng-app ng-controller='rChartsCtrl'"  
    )
    d$addAssets(
      jshead = "http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"
    )
    if (play == T){
      d$setTemplate(chartDiv = sprintf("
        <div class='container'>
         <button ng-click='animateMap()'>Play</button>
         <div id='{{chartId}}' class='rChart datamaps'></div>  
        </div>
        <script>
          function rChartsCtrl($scope, $timeout){
            $scope.keynum = %s;
              $scope.animateMap = function(){
              if ($scope.keynum === Object.keys(chartParams.newData).length){
                return;
              }
              map{{chartId}}.updateChoropleth(chartParams.newData[Object.keys(chartParams.newData)[$scope.keynum]]);
              $scope.keynum += 1
              $timeout($scope.animateMap, 1000)
            }
          }
       </script>", 0  )
      )

    } else {
      d$setTemplate(chartDiv = sprintf("
        <div class='container'>
          <input id='slider' type='range' min=%s max=%s ng-model='value' width=200>
          <div id='{{chartId}}' class='rChart datamaps'></div>  
        </div>
        <script>
          function rChartsCtrl($scope){
            $scope.month = %s;
            $scope.$watch('month', function(newMonth){
              map{{chartId}}.updateChoropleth(chartParams.newData[newMonth]);
            })
          }
       </script>", range_[1], range_[6], range_[1])
      )
    }
    d$set(newData = data, data = data[[1]])

    } else {
    d$set(data = dlply(data, fml$right.name))
    }
    return(d)
  }

重要な部分を切り分けるために、下に貼り付けて説明できるようにします。 range_文字で機能しない要約を使用したため、に変更しました

    range_ = sort(unique(data[[animate]]))

実際にこれを排除することはできますが、それは別のトピックです。文字を使用しているため機能しないため、$scope.month += 1インデックスを使用してデータのキーをループします。最初は0 に設定し、最後に到達するまで$scope.keynum = %s1 を追加します。$scope.keynum += 1$scope.keynum === Object.keys(chartParams.newData).length

      d$setTemplate(chartDiv = sprintf("
        <div class='container'>
         <button ng-click='animateMap()'>Play</button>
         <div id='{{chartId}}' class='rChart datamaps'></div>  
        </div>
        <script>
          function rChartsCtrl($scope, $timeout){
            $scope.keynum = %s;
              $scope.animateMap = function(){
              if ($scope.keynum === Object.keys(chartParams.newData).length){
                return;
              }
              map{{chartId}}.updateChoropleth(chartParams.newData[Object.keys(chartParams.newData)[$scope.keynum]]);
              $scope.keynum += 1
              $timeout($scope.animateMap, 1000)
            }
          }
       </script>", 0  )
      )

これらの R+Javascipt+Angular はデバッグが非常に難しいため、これが役立つことを願っています。何が起こっているのかを説明しているこの投稿を見たと思いますが、まだ投稿していない場合に備えて投稿します。

これが再現可能なコード全体です。

library(rCharts)
library(rMaps)
library(plyr)

dt <- structure(list(month = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("2013-03", 
"2013-04", "2013-05", "2013-06", "2013-07", "2013-08", "2013-09", 
"2013-10", "2013-11", "2013-12", "2014-01", "2014-02", "2014-03", 
"2014-04", "2014-05", "2014-06", "2014-07", "2014-08"), class = "factor"), 
iso = structure(c(2L, 5L, 6L, 7L, 8L, 15L), .Label = c("ABW", 
"AFG", "AGO", "AIA", "ALB", "ARE", "ARG", "AUS", "AUT", "AZE", 
"BEL", "BEN", "BFA", "BGD", "BGR", "BHR", "BHS", "BIH", "BLR", 
"BLZ", "BMU", "BRA", "BRB", "BWA", "CAF", "CAN", "CHE", "CHL", 
"CHN", "CMR", "COL", "COM", "CRI", "CUB", "CYM", "CYP", "CZE", 
"DEU", "DJI", "DMA", "DNK", "DOM", "DZA", "ECU", "EGY", "ERI", 
"ESP", "EST", "ETH", "FIN", "FJI", "FRA", "FRO", "GAB", "GBR", 
"GEO", "GGY", "GHA", "GIB", "GIN", "GLP", "GMB", "GNQ", "GRC", 
"GRD", "GTM", "GUF", "GUM", "GUY", "HKG", "HND", "HRV", "HTI", 
"HUN", "IDN", "IMN", "IND", "IRL", "IRQ", "ISL", "ISR", "ITA", 
"JAM", "JEY", "JOR", "JPN", "KAZ", "KEN", "KGZ", "KHM", "KWT", 
"LBN", "LBR", "LBY", "LCA", "LKA", "LSO", "LTU", "LUX", "LVA", 
"MAR", "MCO", "MDV", "MEX", "MLI", "MLT", "MMR", "MNG", "MOZ", 
"MRT", "MUS", "MWI", "MYS", "NAM", "NCL", "NER", "NGA", "NIC", 
"NLD", "NOR", "NPL", "NZL", "OMN", "PAK", "PAN", "PER", "PHL", 
"PNG", "POL", "PRI", "PRT", "PRY", "QAT", "ROU", "RWA", "SAU", 
"SDN", "SEN", "SGP", "SLB", "SLE", "SLV", "SOM", "SRB", "SSD", 
"SUR", "SVK", "SVN", "SWE", "SYC", "TGO", "THA", "TJK", "TKM", 
"TON", "TTO", "TUN", "TUR", "UGA", "UKR", "URY", "USA", "UZB", 
"VNM", "VUT", "WSM", "YEM", "ZAF", "ZMB", "ZWE"), class = "factor"), 
volume = c(1L, 1L, 5L, 4L, 12L, 10L)), .Names = c("month", 
"iso", "volume"), row.names = c(NA, 6L), class = "data.frame")


  Mchoropleth <- function(x, data, pal = "Blues", ncuts = 5, animate = NULL, play = F, map = 
   'world', legend = TRUE, labels = TRUE, ...){
    d <- Datamaps$new()
    fml = lattice::latticeParseFormula(x, data = data)
    data = transform(data, 
    fillKey = cut(
      fml$left, 
      unique(quantile(fml$left, seq(0, 1, 1/ncuts))),
      ordered_result = TRUE
     )
    )
    fillColors = RColorBrewer::brewer.pal(ncuts, pal)
    d$set(
    scope = map, 
    fills = as.list(setNames(fillColors, levels(data$fillKey))), 
    legend = legend,
    labels = labels,
    ...
    )
    if (!is.null(animate)){

    range_ = sort(unique(data[[animate]]))


    data = dlply(data, animate, function(x){
      y = toJSONArray2(x, json = F)
      names(y) = lapply(y, '[[', fml$right.name)
      return(y)
     })
     d$set(
      bodyattrs = "ng-app ng-controller='rChartsCtrl'"  
    )
    d$addAssets(
      jshead = "http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"
    )
    if (play == T){
      d$setTemplate(chartDiv = sprintf("
        <div class='container'>
         <button ng-click='animateMap()'>Play</button>
         <div id='{{chartId}}' class='rChart datamaps'></div>  
        </div>
        <script>
          function rChartsCtrl($scope, $timeout){
            $scope.keynum = %s;
              $scope.animateMap = function(){
              if ($scope.keynum === Object.keys(chartParams.newData).length){
                return;
              }
              map{{chartId}}.updateChoropleth(chartParams.newData[Object.keys(chartParams.newData)[$scope.keynum]]);
              $scope.keynum += 1
              $timeout($scope.animateMap, 1000)
            }
          }
       </script>", 0  )
      )

    } else {
      d$setTemplate(chartDiv = sprintf("
        <div class='container'>
          <input id='slider' type='range' min=%s max=%s ng-model='value' width=200>
          <div id='{{chartId}}' class='rChart datamaps'></div>  
        </div>
        <script>
          function rChartsCtrl($scope){
            $scope.month = %s;
            $scope.$watch('month', function(newMonth){
              map{{chartId}}.updateChoropleth(chartParams.newData[newMonth]);
            })
          }
       </script>", range_[1], range_[6], range_[1])
      )
    }
    d$set(newData = data, data = data[[1]])

    } else {
    d$set(data = dlply(data, fml$right.name))
    }
    return(d)
  }


  dt2 <- data.frame(
    iso = as.factor(rep(levels(dt$iso),length(levels(dt$month))))
    ,month = unlist(lapply(1:length(levels(dt$month)),function(m){
      rep(levels(dt$month)[m],length(levels(dt$iso)))
    }))
    ,volume = runif(length(levels(dt$month))*length(levels(dt$iso)),0,100)
  )


  # no reason to have factors
  # so I suggest converting to character
  dt2$iso <- as.character(dt2$iso)
  dt2$month <- as.character(dt2$month)

  mChoro <- Mchoropleth(
    volume ~ iso
    , data = dt2
    , pal = 'PuRd'
    , cuts = 3
    , animate = "month"
    , play = T
  )
  mChoro
于 2014-09-11T15:52:07.733 に答える