0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rの3次元散布図(scatterplot3d())での軸の反転方法

Last updated at Posted at 2020-12-29

Rにおいて3次元散布図を描く関数scatterplot3d()について、軸の反転方法を紹介します。
厳密に言うと、軸が反転しているように見せる方法になります。

これにより、scatterplot3d()でいわゆる「右手系座標」が描画できるようになります。

y軸反転前(手前から奥方向)

20201228-1.png

y軸反転後(奥から手前)

20201228-2.png

環境

  • OS: Windows10
  • R: R x64 4.0.3
  • RStudio: Version 1.3.1093

plot()におけるxlimを使った軸の反転方法

Rにおいて、plot()を用いて2次元の散布図を描く場合、xlimylimを用いることで、簡単に軸の向きを反転させることができます。

x軸反転前(デフォルト)

ソースコード

example1.r
n <- 100
x <- seq(0,2*pi,length=n)
y <- array(1:n)

for(i in 1:n){
  y[i] <- sin(x[i])
}

par(mar=c(5,4,4,2))
plot(x,y,
     xlim=c(0,7), #x軸反転前(0->7)
     pch=c(19,rep(1,n-2),19),
     col=c("#FF0000",rep("#000000",n-2),"#00FF00"))

結果

20201228-3.png

x軸反転後

ソースコード

example2.r
n <- 100
x <- seq(0,2*pi,length=n)
y <- array(1:n)

for(i in 1:n){
  y[i] <- sin(x[i])
}

par(mar=c(5,4,4,2))
plot(x,y,
     xlim=c(7,0), #x軸反転後(7->0)
     pch=c(19,rep(1,n-2),19),
     col=c("#FF0000",rep("#000000",n-2),"#00FF00"))

結果

20201228-4.png

scatterplot3d()でもxlimを使うが…

同じようなことを、3次元の散布図を描くscatterplot3d()についても行いたいのですが、どうやら仕様により、xlim等を使っての軸反転はできないようです。

y軸反転前

ソースコード

example3.r
n <- 100
x <- seq(0,2*pi,length=n)
y <- x
z <- array(1:n)

for(i in 1:n){
  z[i] <- sin(x[i])
}

scatterplot3d(x,y,z,
              pch=c(19,rep(1,n-2),19),
              color=c("#FF0000",rep("#000000",n-2),"#00FF00"),
              xlab="x",ylab="y",zlab="z",
              ylim=c(0,7), #y軸反転前(0->7)
              y.margin.add=0.2
              )

結果

20201228-5.png

y軸反転…を意図

ソースコード

example4.r
n <- 100
x <- seq(0,2*pi,length=n)
y <- x
z <- array(1:n)

for(i in 1:n){
  z[i] <- sin(x[i])
}

scatterplot3d(x,y,z,
              pch=c(19,rep(1,n-2),19),
              color=c("#FF0000",rep("#000000",n-2),"#00FF00"),
              xlab="x",ylab="y",zlab="z",
              ylim=c(7,0), #y軸反転を意図(7->0)
              y.margin.add=0.2
              )

結果(y軸反転せず)

20201228-5.png

公式ドキュメントにも、xlimylimzlimの項に

Note that setting enlarged limits may not work as exactly as expected (a known but unfixed bug).

とあるので、もしかしたらこれが影響しているのかしれません。

それでもscatterplot3d()で軸反転させたい!

それでもやっぱり軸反転させたいので、あたかも軸反転しているかのように見せる手段を考えました。

幸い、scatterplot3d()にはx.ticklabs等の引数があり、これにより軸の目盛りラベルの値を上書きすることができます。

これを用いて、反転させたい成分に対して、

  • プロットデータの対象成分について、値を反転させる
  • 対象成分の軸の目盛りラベルの値も反転させる

の2つをすることで、あたかも軸反転しているように見せます。

プロットデータの値を反転させる

仮に、点$x$を点$a$で反転させたいとします。
このとき、反転後の点を$x'$とすると、$x'$は
  $x'=-(x-a)+a=2a-x$
により算出されます。
20201228-6.png

プロットデータの反転させたい成分について、同様のことをすることで、反転することができます。
R上のコードでは、具体的に以下のように書けばOKです。

example5.r
x <- 2*a - x

ところで、反転の中心となるaはどのように決めればよいでしょう?
反転したい軸の範囲の中心を設定してあげれば、きれいに軸反転したように見えます。

例えば、y軸について反転させたい場合、y軸の最小値を0、最大値を7とすると、

example6.r
ylim_min <- 0
ylim_max <- 7
ylim_ave <- ave(c(ylim_min,ylim_max))

y <- 2*ylim_ave - y

とすることで、y軸の範囲の中心3.5で反転させることができます。

軸の目盛りラベルの値を反転させる

先ほど紹介したx.ticklabs等の引数には、目盛りラベルを小さい方から並べた配列を渡します。

例えば、y軸の目盛りラベルを0から71刻みにしたい場合は、scatterplot3d()の引数に

example7.r
y.ticklabs=seq(0,7,by=1)

と書けばOKです。

今回は、これを反転させたいので、7から0-1刻みの配列を渡せばいいので、

example8.r
y.ticklabs=seq(7,0,by=-1)

となります。

実例

以上をまとめると、以下のソースコードになります。

ソースコード

test.r
n <- 100
x <- seq(0,2*pi,length=n)
y <- x
z <- array(1:n)

ylim_min <- 0
ylim_max <- 7
ylim_ave <- ave(c(ylim_min,ylim_max))

for(i in 1:n){
  z[i] <- sin(x[i])
}

y <- 2*ylim_ave - y

scatterplot3d(x,y,z,
              pch=c(19,rep(1,n-2),19),
              color=c("#FF0000",rep("#000000",n-2),"#00FF00"),
              xlab="x",ylab="y",zlab="z",
              y.ticklabs=seq(7,0,by=-1),
              y.margin.add=0.2
              )

結果

20201228-2.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?