Rの線密度ヒートマップ


8

問題の説明
プロットしたい数千行(約4000)があります。ただし、すべての線を使用してプロットすることは不可能でありgeom_line()、たとえばalpha=0.1、線の密度が高い場所とない場所を示すためだけに使用することはできません。私はPython似たようなものに出くわしました。特に、回答の2番目のプロットは本当に良さそうですが、似たようなものをで達成できるかどうかはわかりませんggplot2。したがって、このようなもの: ここに画像の説明を入力してください

サンプルデータセット
パターンを示すセットを使用してこれを示す方がはるかに理にかなっていますが、ここではランダムな正弦曲線を生成しました。

set.seed(1)
gen.dat <- function(key) {
    c <- sample(seq(0.1,1, by = 0.1), 1)
    time <- seq(c*pi,length.out=100)
    val <- sin(time)
    time = 1:100
    data.frame(time,val,key)
}
dat <- lapply(seq(1,10000), gen.dat) %>% bind_rows()

ここ答えたようなヒートマップ
を試してみました、このヒートマップは、完全な軸上の点の接続(直線など)を考慮せず、時間ごとの「ヒート」を示します。

質問最初の図に示されているのと同様のラインのヒートマップを
使用して、Rでどのようにできggplot2ますか?

回答:


3

あなたのデータは非常に均一な水玉模様の密度になります。

私はこのような少し興味深いデータをいくつか生成しました:

gen.dat <- function(key) {
  has_offset <- runif(1) > 0.5
  time <- seq(1, 1000, length.out = 1000)
  val <- sin(time / 100 + rnorm(1, sd = 0.2) + (has_offset * 1.5)) * 
    rgamma(1, 20, 20)
  data.frame(time,val,key)
}
dat <- lapply(seq(1,1000), gen.dat) %>% bind_rows()

次に、2D密度推定を取得します。kde2dにはpredict関数がないため、LOESSでモデル化します

dens <- MASS::kde2d(dat$time, dat$val, n = 400)
dens_df <- data.frame(with(dens, expand_grid( y, x)), z = as.vector(dens$z))
fit <- loess(z ~ y * x, data = dens_df, span = 0.02)
dat$z <- predict(fit, with(dat, data.frame(x=time, y=val)))

それをプロットすると、次の結果が得られます。

ggplot(dat, aes(time, val, group = key, color = z)) +
  geom_line(size = 0.05) +
  theme_minimal() +
  scale_color_gradientn(colors = c("blue", "yellow", "red"))

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

これはすべて次の要素に大きく依存しています。

  • シリーズ数
  • シリーズの解決
  • kde2dの密度
  • 黄土のスパン

あなたの走行距離は異なる場合があります


かっこいい!
CodeNoob

1
私のデータにTjeboのライブラリの提案を試してみてggplot(dat, aes(time, val, group=key)) +stat_pointdensity(geom = "line", size = 0.05, adjust = 10) + scale_color_gradientn(colors = c("blue", "yellow", "red"))
ロビンGertenbach

それは本当に素晴らしいことです。偉大な、確かにこのルックスを素敵なサンプルデータを提供してくれてありがとうggpointdensity
Tjebo

あなたのデータで私の答えを更新しました。ありがとうございました
Tjebo

1
賞金をありがとう、Tjebo :)最終的にはggpointdensityが見栄えの良いヒアマップを実現すると思います。密度が〜250、-0.5の密度は375 -0.5の密度と同様であるので、その密度は正確かどうか疑問に思いますが、それは単なる勾配である可能性があります
Robin Gertenbach

6

よく見ると、リンクしているグラフは、線ではなく多くの、多くの、多くの点で構成されていることがわかります。

ggpointdensityパッケージには、同様の可視化を行います。非常に多くのデータポイントがあるため、パフォーマンスにかなりの問題があることに注意してください。私は開発者バージョンを使用していmethodます。これには、さまざまな平滑化推定量を使用できるようにする引数が含まれており、明らかに大きな数の処理に役立つからです。クランバージョンもあります。

adjust引数でスムージングを調整できます。

コードのx間隔の密度を上げて、より線のように見せました。ただし、プロットの「ライン」の数をわずかに減らしました。

library(tidyverse)
#devtools::install_github("LKremer/ggpointdensity")
library(ggpointdensity)

set.seed(1)
gen.dat <- function(key) {
  c <- sample(seq(0.1,1, by = 0.1), 1)
  time <- seq(c*pi,length.out=500)
  val <- sin(time)
  time = seq(0.02,100,0.1)
  data.frame(time,val,key)
}
dat <- lapply(seq(1, 1000), gen.dat) %>% bind_rows()

ggplot(dat, aes(time, val)) + 
  geom_pointdensity(size = 0.1, adjust = 10) 
#> geom_pointdensity using method='kde2d' due to large number of points (>20k)

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

update 興味深いサンプルデータを作成して くれたユーザーRobert Gertenbachに感謝します。ここでは、このデータでのggpointdensityの推奨される使用法を示します。

library(tidyverse)
library(ggpointdensity)

gen.dat <- function(key) {
  has_offset <- runif(1) > 0.5
  time <- seq(1, 1000, length.out = 1000)
  val <- sin(time / 100 + rnorm(1, sd = 0.2) + (has_offset * 1.5)) * 
    rgamma(1, 20, 20)
  data.frame(time,val,key)
}

dat <- lapply(seq(1,1000), gen.dat) %>% bind_rows()
ggplot(dat, aes(time, val, group=key)) +stat_pointdensity(geom = "line", size = 0.05, adjust = 10) + scale_color_gradientn(colors = c("blue", "yellow", "red"))

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


答えてくれてありがとう。技術的にはすべての線と散布(点)プロットを交換できますが、それは基礎となるデータに依存します-私の質問では、画像が点の「ジッター」ではなくパターン/相関を示すことを明確に目的としていた場合、説明のために、プロットでは、根底にある特徴的な洞構造を明らかにしていません。
CodeNoob

@CodeNoobサンプルデータは理想的でない場合があります。私はパターンを見ることができると思います-それは自然に規則的なグリッドを作成しています。一般に、線を点に変換する場合、メソッドは機能するはずです。しかし、それは私があなたの質問に賞金を差し上げる理由でもあります、なぜならそこに解決策のためのより良いアイデアがあるかもしれないからです。これは興味深い問題です。
Tjebo

1
@codenoobパターンを表示するのに苦労している場合は、画像を小さくして、単一のドットを表示しないようにします。あなたが提供したサンプル画像でも同じことが起こります。それは解決の問題です。
Tjebo

1
これを私のデータで使用すると、ggplot(dat, aes(time, val, group=key)) +stat_pointdensity(geom = "line", size = 0.05, adjust = 10) + scale_color_gradientn(colors = c("blue", "yellow", "red"))本当に見栄えが良いものになります!
Robin Gertenbach

-1

私が使用して、以下の解決策を考え出したgeom_segment()場合、私はわからないが、geom_segment()それとしてのみチェックを移動するための方法であるペアワイズ値がある場合、正確に(私の質問のように)ヒートマップ内で互いに近い値も影響を与えるのに対し、同じまったく同じというよりはむしろ「熱」。

# Simple stats to get all possible line segments
vals <- unique(dat$time)
min.val = min(vals)
max.val = max(vals)

# Get all possible line segments
comb.df <- data.frame(
  time1 = min.val:(max.val - 1),
  time2 = (min.val + 1): max.val
)

# Join the original data to all possible line segments
comb.df <- comb.df %>% 
  left_join(dat %>% select(time1 = time, val1 = val, key )) %>%
  left_join(dat %>% select(time2 = time, val2 = val, key ))

# Count how often each line segment occurs in the data
comb.df <- comb.df %>% 
  group_by(time1, time2, val1, val2) %>%
  summarise(n = n_distinct(key))

# ggplot2 to plot segments
ggplot(comb.df %>% arrange(n)) +
  geom_segment(aes(x = time1, y = val1, xend = time2, yend = val2, color = n), alpha =0.9) +
  scale_colour_gradient( low = 'green', high = 'red')  +
  theme_bw()

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.