観察によってヒストグラム観察を構築するためにgganimateを使用しますか?より大きなデータセット(〜n = 5000)で機能する必要がある


12

正規分布からポイントをサンプリングしgganimate、最後のフレームに完全なドットプロットが表示されるまで、パッケージを使用してドットプロットを1つずつ作成します。

大規模なデータセット〜5,000〜20,000ポイントで機能するソリューションが不可欠です。

ここに私がこれまでに持っているコードがあります:

library(gganimate)
library(tidyverse)

# Generate 100 normal data points, along an index for each sample 
samples <- rnorm(100)
index <- seq(1:length(samples))

# Put data into a data frame
df <- tibble(value=samples, index=index)

dfは次のようになります。

> head(df)
# A tibble: 6 x 2
    value index
    <dbl> <int>
1  0.0818     1
2 -0.311      2
3 -0.966      3
4 -0.615      4
5  0.388      5
6 -1.66       6

静的プロットは正しいドットプロットを示しています。

# Create static version
plot <- ggplot(data=df, mapping=aes(x=value))+
          geom_dotplot()

ただし、gganimateバージョンには対応していません(以下を参照)。X軸にドットを配置するだけで、積み重ねません。

plot+
  transition_reveal(along=index)

静的プロット

ここに画像の説明を入力してください

これに似たものが理想的です:クレジット:https : //gist.github.com/thomasp85/88d6e7883883315314f341d2207122a1 ここに画像の説明を入力してください


へや。検索性を高めるために、別のタイトルを提案してもよいですか?私は本当にこのアニメーションヒストグラムが好きになり、素晴らしい視覚化だと思います... "アニメーションドットヒストグラム、観察によって構築された観察"のようなSTHがおそらくより適切でしょうか?
チェボ

回答:


11

別のオプションは、別のgeomでポイントを描くことです。最初にデータ(およびビニング)を数える必要がありますが、データを長くする必要はありません。

たとえば、を使用できますgeom_pointが、ポイントの寸法を正しくして、タッチする/タッチしないようにすることが課題です。これは、デバイス/ファイルサイズによって異なります。

しかし、あなたはggforce::geom_ellipseあなたのドットを描くのに使うこともできます:)

geom_point(デバイスの寸法に関する試行錯誤)

library(tidyverse)
library(gganimate)

set.seed(42)
samples <- rnorm(100)
index <- seq(1:length(samples))
df <- tibble(value = samples, index = index)

bin_width <- 0.25

count_data <- # some minor data transformation
  df %>%
  mutate(x = plyr::round_any(value, bin_width)) %>%
  group_by(x) %>%
  mutate(y = seq_along(x))

plot <-
  ggplot(count_data, aes(group = index, x, y)) + # group by index is important
  geom_point(size = 5)

p_anim <- 
  plot +
  transition_reveal(index)

animate(p_anim, width = 550, height = 230, res = 96)

geom_ellipse(ポイントサイズのフルコントロール)

library(ggforce)
plot2 <- 
  ggplot(count_data) +
  geom_ellipse(aes(group = index, x0 = x, y0 = y, a = bin_width/2, b = 0.5, angle = 0), fill = 'black') +
  coord_equal(bin_width) # to make the dots look nice and round

p_anim2 <- 
  plot2 +
  transition_reveal(index) 

animate(p_anim2) 

あなたがトーマスの驚くべき例に提供するリンクを更新すると、彼は同様のアプローチを使用していることがわかります-彼はgeom_ellipseの代わりにgeom_circleを使用しています。

「落下」効果を得るにはtransition_states、長い時間と毎秒多くのフレームが必要です。

p_anim2 <- 
  plot2 +
  transition_states(states = index, transition_length = 100, state_length = 1) +
  shadow_mark() +
  enter_fly(y_loc = 12) 

animate(p_anim2, fps = 40, duration = 20) 

2020-04-29にreprexパッケージ(v0.3.0)によって作成されました

ggplot dotplotgeom_dotplotの適切な使用法は何ですか?


Y値に応じた列ではなく、1つずつポイントを探しています。
最大

2
@max更新を参照-yをインデックスに置き換えるだけです。
Tjebo

3

これを試して。基本的な考え方は、obsをフレームにグループ化することです。つまり、インデックスで分割してから、サンプルをフレームに蓄積します。これを実現するためのよりエレガントな方法ですが、機能します。

library(ggplot2)
library(gganimate)
library(dplyr)
library(purrr)

set.seed(42)

# example data
samples <- rnorm(100)
index <- seq(1:length(samples))

# Put data into a data frame
df <- tibble(value=samples, index=index)

# inflated df. Group obs together into frames
df_ani <- df %>% 
  split(.$index) %>% 
  accumulate(~ bind_rows(.x, .y)) %>% 
  bind_rows(.id = "frame") %>% 
  mutate(frame = as.integer(frame))
head(df_ani)
#> # A tibble: 6 x 3
#>   frame  value index
#>   <int>  <dbl> <int>
#> 1     1  1.37      1
#> 2     2  1.37      1
#> 3     2 -0.565     2
#> 4     3  1.37      1
#> 5     3 -0.565     2
#> 6     3  0.363     3

p_gg <- ggplot(data=df, mapping=aes(x=value))+
  geom_dotplot()
p_gg
#> `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.

p_anim <- ggplot(data=df_ani, mapping=aes(x=value))+
  geom_dotplot()

anim <- p_anim + 
  transition_manual(frame) +
  ease_aes("linear") +
  enter_fade() +
  exit_fade()
anim
#> `stat_bindot()` using `bins = 30`. Pick better value with `binwidth`.

2020-04-27にreprexパッケージ(v0.3.0)によって作成されました


これは機能しますが、テーブルには複製されたデータの多くの行が含まれているため、大規模なデータセットではすぐに実行不可能になります。
最大

たとえば、5000ポイントをプロットする場合、データフレームには1200万行があります:(
最大

返事遅れてすみません。現在少し忙しいです。はい。あなたの言ってる事がわかります。この種の問題には、より優れた、より率直な解決策が必要だと私は確信しています。しかし、私はまだgganimateの初心者であり、今までその可能性と機能のすべてをチェックする時間はありませんでした。だから、今のところもっと良い解決策を思いつくことはできません。
ステファン

3

ここでの鍵は、このアニメーションを手動で作成する方法を想像することだと思います。つまり、結果のドットプロットに一度に1つの観測点を追加します。このことを念頭に置いて、ここで使用したアプローチggplotは、プロットレイヤー=観測数で構成されるオブジェクトを作成し、を介してレイヤーごとにステップスルーすることtransition_layerでした。

# create the ggplot object
df <- data.frame(id=1:100, y=rnorm(100))

p <- ggplot(df, aes(y))

for (i in df$id) {
  p <- p + geom_dotplot(data=df[1:i,])
}

# animation
anim <- p + transition_layers(keep_layers = FALSE) +
    labs(title='Number of dots: {frame}')
animate(anim, end_pause = 20, nframes=120, fps=20)

ここに画像の説明を入力してください

keep_layers=FALSEプロットしすぎないように設定していることに注意してください。初期をプロットするとggplotオブジェクト、最初の観測値が100回プロットされ、2番目の観測値が99回プロットされるので、私の意味がわかります...など。

大規模なデータセットのスケーリングについてはどうですか?

フレーム数=観測数なので、スケーラビリティを調整する必要があります。ここでは、#フレームを一定に保ちます。つまり、コードでフレームをセグメントにグループ化する必要があります。これは、seq()関数を使用して、を指定して行いlength.out=100ます。新しい例でも、データセットにが含まれていることに注意してくださいn=5000。フレーム内のドットプロットを維持するには、ドットのサイズを本当に小さくする必要があります。私はおそらくここでドットを少し小さすぎましたが、あなたは考えを理解しています。これで、#フレーム=観測グループの数になります。

df <- data.frame(id=1:5000, y=rnorm(5000))

p <- ggplot(df, aes(y))

for (i in seq(0,length(df$id), length.out=100)) {
  p <- p + geom_dotplot(data=df[1:i,], dotsize=0.08)
}

anim <- p + transition_layers(keep_layers=FALSE) +
  labs(title='Frame: {frame}')

animate(anim, end_pause=20, nframes=120, fps=20)

ここに画像の説明を入力してください


これは小さなデータセットに対しては適切に機能しますが、中程度に大きなデータ(n = 5000)に対しても適切にスケーリングされません。
最大

ここにエラーがありますn = 5000のレポート:エラー:Cスタック使用率7969904は制限に近すぎます
最大

はい、ここでの例にはフレーム=観測数があります。#フレームを100に一定に保ち、フレーム=観測グループの
chemdork123
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.