swirl_3d {rearrr}R Documentation

Swirl the values around an origin in 3 dimensions

Description

[Experimental]

The values are swirled counterclockwise around a specified origin. The swirling is done by rotating around the origin, basing the degrees for each rotation-axis on the distances to the origin as so:

x_degrees = scale_fn(distances) / (2 * x_radius) * 360

The origin can be supplied as coordinates or as a function that returns coordinates. The latter can be useful when supplying a grouped data.frame and swirling around e.g. the centroid of each group.

Usage

swirl_3d(
  data,
  x_col,
  y_col,
  z_col,
  x_radius = 0,
  y_radius = 0,
  z_radius = 0,
  suffix = "_swirled",
  origin = NULL,
  origin_fn = NULL,
  scale_fn = identity,
  keep_original = TRUE,
  degrees_col_name = ".degrees",
  radius_col_name = ".radius",
  origin_col_name = ".origin",
  overwrite = FALSE
)

Arguments

data

data.frame or vector.

x_col, y_col, z_col

Name of x/y/z column in `data`. All must be specified.

x_radius, y_radius, z_radius

Radiuses of the most-inner swirls around each axis (in the simplest case). Can be vectors with multiple radiuses.

E.g. the `x_radius` specifies the radius when rotating around the x-axis, not the radius on the x-axis.

Note: With a custom `scaling_fn`, these might not be the actual swirl radiuses anymore. Think of them more as width settings where a larger number leads to fewer full rotations.

suffix

Suffix to add to the names of the generated columns.

Use an empty string (i.e. "") to overwrite the original columns.

origin

Coordinates of the origin to swirl around. Vector with 3 elements (i.e. origin_x, origin_y, origin_z). Ignored when `origin_fn` is not NULL.

origin_fn

Function for finding the origin coordinates.

Input: Each column will be passed as a vector in the order of `cols`.

Output: A vector with one scalar per dimension.

Can be created with create_origin_fn() if you want to apply the same function to each dimension.

E.g. `create_origin_fn(median)` would find the median of each column.

Built-in functions are centroid(), most_centered(), and midrange()

scale_fn

Function for scaling the distances before calculating the degrees.

Input: A numeric vector (the distances).

Output: A numeric vector (the scaled distances) of the same length.

E.g.:

function(d){

⁠ ⁠d ^ 1.5

}

keep_original

Whether to keep the original columns. (Logical)

Some columns may have been overwritten, in which case only the newest versions are returned.

degrees_col_name

Name of new column with the degrees. If NULL, no column is added.

Also adds a string version with the same name + "_str", making it easier to group by the degrees when plotting multiple rotations.

radius_col_name

Name of new column with the radiuses. If NULL, no column is added.

origin_col_name

Name of new column with the origin coordinates. If NULL, no column is added.

overwrite

Whether to allow overwriting of existing columns. (Logical)

Value

data.frame (tibble) with new columns containing the swirled x- and y-values, the degrees, the radiuses, and the origin coordinates.

Author(s)

Ludvig Renbo Olsen, r-pkgs@ludvigolsen.dk

See Also

Other mutate functions: apply_transformation_matrix(), cluster_groups(), dim_values(), expand_distances(), expand_distances_each(), flip_values(), roll_values(), rotate_2d(), rotate_3d(), shear_2d(), shear_3d(), swirl_2d()

Other rotation functions: rotate_2d(), rotate_3d(), swirl_2d()

Other distance functions: closest_to(), dim_values(), distance(), expand_distances(), expand_distances_each(), furthest_from(), swirl_2d()

Examples

# Attach packages
library(rearrr)
library(dplyr)
has_ggplot <- require(ggplot2)  # Attach if installed

# Set seed
set.seed(4)

# Create a data frame
df <- data.frame(
  "x" = 1:50,
  "y" = 1:50,
  "z" = 1:50,
  "r1" = runif(50),
  "r2" = runif(50) * 35,
  "o" = 1,
  "g" = rep(1:5, each = 10)
)

# Swirl values around (0, 0, 0)
swirl_3d(
  data = df,
  x_radius = 45,
  x_col = "x",
  y_col = "y",
  z_col = "z",
  origin = c(0, 0, 0)
)

# Swirl around the centroid
df_swirled <- swirl_3d(
  data = df,
  x_col = "x",
  y_col = "y",
  z_col = "z",
  x_radius = c(100, 0, 0),
  y_radius = c(0, 100, 0),
  z_radius = c(0, 0, 100),
  origin_fn = centroid
)

df_swirled

# Plot swirls
if (has_ggplot){
  ggplot(df_swirled, aes(x = x_swirled, y = y_swirled, color = .radius_str, alpha = z_swirled)) +
    geom_vline(xintercept = mean(df$x), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$y), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_path(alpha = .4) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "radius", alpha = "z (opacity)")
}

## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_swirled$x_swirled,
  y = df_swirled$y_swirled,
  z = df_swirled$z_swirled,
  type = "scatter3d",
  mode = "markers",
  color = df_swirled$.radius_str
)

## End(Not run)

# Swirl around the centroid
df_swirled <- swirl_3d(
  data = df,
  x_col = "x",
  y_col = "y",
  z_col = "z",
  x_radius = c(50, 0, 0),
  y_radius = c(0, 50, 0),
  z_radius = c(0, 0, 50),
  origin_fn = centroid
)

df_swirled

# Plot swirls
if (has_ggplot){
  ggplot(df_swirled, aes(x = x_swirled, y = y_swirled, color = .radius_str, alpha = z_swirled)) +
    geom_vline(xintercept = mean(df$x), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$y), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_path(alpha = .4) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "radius", alpha = "z (opacity)")
}

## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_swirled$x_swirled,
  y = df_swirled$y_swirled,
  z = df_swirled$z_swirled,
  type = "scatter3d",
  mode = "markers",
  color = df_swirled$.radius_str
)

## End(Not run)


df_swirled <- swirl_3d(
  data = df,
  x_col = "x",
  y_col = "y",
  z_col = "z",
  x_radius = c(25, 50, 25, 25),
  y_radius = c(50, 75, 100, 25),
  z_radius = c(75, 25, 25, 25),
  origin_fn = centroid,
  scale_fn = function(x) {
    x^0.81
  }
)

# Plot swirls
if (has_ggplot){
  ggplot(df_swirled, aes(x = x_swirled, y = y_swirled, color = .radius_str, alpha = z_swirled)) +
    geom_vline(xintercept = mean(df$x), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$y), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_path(alpha = .4) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "radius", alpha = "z (opacity)")
}


## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_swirled$x_swirled,
  y = df_swirled$y_swirled,
  z = df_swirled$z_swirled,
  type = "scatter3d",
  mode = "markers",
  color = df_swirled$.radius_str
)

## End(Not run)


#
# Swirl random data
# The trick lies in finding the right radiuses
#

# Swirl the random columns
df_swirled <- swirl_3d(
  data = df,
  x_col = "r1",
  y_col = "r2",
  z_col = "o",
  x_radius = c(0, 0, 0, 0),
  y_radius = c(0, 30, 60, 90),
  z_radius = c(10, 10, 10, 10),
  origin_fn = centroid
)

# Not let's rotate it every 10 degrees
df_rotated <- df_swirled %>%
  rotate_3d(
    x_col = "r1_swirled",
    y_col = "r2_swirled",
    z_col = "o_swirled",
    x_deg = rep(0, 36),
    y_deg = rep(0, 36),
    z_deg = (1:36) * 10,
    suffix = "",
    origin = df_swirled$.origin[[1]],
    overwrite = TRUE
  )

# Plot rotated swirls
if (has_ggplot){
  ggplot(
    df_rotated,
    aes(
      x = r1_swirled,
      y = r2_swirled,
      color = .degrees_str,
      alpha = o_swirled
    )
  ) +
    geom_vline(xintercept = mean(df$r1), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$r2), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_point(show.legend = FALSE) +
    theme_minimal() +
    labs(x = "r1", y = "r2", color = "radius", alpha = "o (opacity)")
}


[Package rearrr version 0.3.4 Index]