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

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

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

###y軸反転前（手前から奥方向）
![20201228-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/e3d62519-68c5-c492-9d0e-f03d427689bf.png)

###y軸反転後（奥から手前）
![20201228-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/18e5d9a3-3f0d-19af-3e59-d9d222e0188b.png)

#環境
- OS: Windows10
- R: R x64 4.0.3
- RStudio: Version 1.3.1093

#`plot()`における`xlim`を使った軸の反転方法
Rにおいて、`plot()`を用いて2次元の散布図を描く場合、`xlim`や`ylim`を用いることで、簡単に軸の向きを反転させることができます。

###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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/886547d1-cb04-7bfb-db92-991f41b941b8.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/33a3214c-13f9-c1e5-b799-fd5f7a7eb26f.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/5b628080-bba7-376c-91c8-61c27942b012.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/5b628080-bba7-376c-91c8-61c27942b012.png)

[公式ドキュメント](https://www.rdocumentation.org/packages/scatterplot3d/versions/0.3-41/topics/scatterplot3d "scatterplot3d function | R Documentation")にも、`xlim`、`ylim`、`zlim`の項に

>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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/0da9a104-9b2b-946f-fbf9-f483bc06d833.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`から`7`の`1`刻みにしたい場合は、`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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179111/18e5d9a3-3f0d-19af-3e59-d9d222e0188b.png)