Skip to content

Commit

Permalink
Merge pull request #12 from neuropsychology/0.0.3
Browse files Browse the repository at this point in the history
0.0.3
  • Loading branch information
DominiqueMakowski committed Nov 11, 2017
2 parents 0cfb92d + e5366c3 commit 458d54f
Show file tree
Hide file tree
Showing 10 changed files with 442 additions and 29 deletions.
5 changes: 4 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: psycho
Type: Package
Title: Efficient and Publishing-Oriented Workflow for Psychological Science
Version: 0.0.2
Version: 0.0.3
Authors@R: c(
person("Dominique",
"Makowski",
Expand Down Expand Up @@ -33,6 +33,9 @@ Imports:
tidyverse,
rtf,
psych,
MASS,
nFactors,
qgraph,
ppcor,
corrplot,
rstanarm,
Expand Down
10 changes: 10 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export(find_season)
export(format_digit)
export(format_p)
export(interpret_d)
export(n_factors)
export(normalize)
export(values)
import(corrplot)
Expand All @@ -23,10 +24,19 @@ import(ppcor)
import(purrr)
import(rstanarm)
import(tidyr)
importFrom(MASS,ginv)
importFrom(MASS,mvrnorm)
importFrom(MuMIn,r.squaredGLMM)
importFrom(MuMIn,std.coef)
importFrom(nFactors,moreStats)
importFrom(nFactors,nScree)
importFrom(psych,VSS)
importFrom(psych,corr.p)
importFrom(psych,corr.test)
importFrom(qgraph,cor_auto)
importFrom(stats,cov)
importFrom(stats,dnorm)
importFrom(stats,ecdf)
importFrom(stats,na.omit)
importFrom(stats,qnorm)
importFrom(stats,quantile)
9 changes: 9 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# 0.0.2 (2017-11-10)

### Breaking changes
### New functions / parameters
- `n_factors`: How many factors to retain for PCA or factor analysis?
### Major changes
### Minor changes


# 0.0.2 (2017-10-12)

### Breaking changes
Expand Down
2 changes: 1 addition & 1 deletion R/format_p.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ format_p <- function(pvalues) {
ifelse(pvalues < 0.001, "< .001***",
ifelse(pvalues < 0.01, "< .01**",
ifelse(pvalues < 0.05, "< .05*",
ifelse(pvalues < 0.1, paste0(round(pvalues, 2), "\xB0"),
ifelse(pvalues < 0.1, paste0("= ", round(pvalues, 2), "\xB0"),
"> .1"))))
}
186 changes: 186 additions & 0 deletions R/n_factors.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#' Find Optimal Factor Number.
#'
#' Find optimal factor number using various solutions.
#'
#' @param df The dataframe
#' @param rotate What rotation to use c("none", "varimax", "oblimin","promax")
#' @param fm Factoring method – fm="pa" Principal Axis Factor Analysis,
#' fm = "minres" minimum residual (OLS) factoring fm="mle" Maximum Likelihood FA,
#' fm="pc" Principal Components"
#' @param n_max How many factors to test.
#'
#' @return output
#'
#' @examples
#' df <- dplyr::select_if(attitude, is.numeric)
#' results <- psycho::n_factors(df)
#'
#' summary(results)
#' plot(results)
#'
#' # See details on methods
#' psycho::values(results)$methods
#'
#' @author \href{https://dominiquemakowski.github.io/}{Dominique Makowski}
#'
#' @importFrom qgraph cor_auto
#' @importFrom psych VSS
#' @importFrom MASS mvrnorm
#' @importFrom MASS ginv
#' @importFrom nFactors moreStats
#' @importFrom nFactors nScree
#' @importFrom stats cov
#' @importFrom stats dnorm
#' @importFrom stats qnorm
#' @export
n_factors <- function(df, rotate="varimax", fm="minres", n_max=8){

# Copy the parallel function from nFactors to correct the use of mvrnorm
parallel <- function (subject = 100, var = 10, rep = 100, cent = 0.05,
quantile = cent, model = "components",
sd = diag(1, var), ...)
{
r <- subject
c <- var
y <- matrix(c(1:r * c), nrow = r, ncol = c)
evpea <- NULL
for (k in c(1:rep)) {
y <- MASS::mvrnorm(n = r, mu = rep(0, var), Sigma = sd, empirical = FALSE)
corY <- cov(y, ...)
if (model == "components")
diag(corY) <- diag(sd)
if (model == "factors")
corY <- corY - MASS::ginv(diag(diag(MASS::ginv(corY))))
evpea <- rbind(evpea, eigen(corY)[[1]])
}
SEcentile <- function(sd, n = 100, p = 0.95) {
return(sd/sqrt(n) * sqrt(p * (1 - p))/dnorm(qnorm(p)))
}
mevpea <- sapply(as.data.frame(evpea), mean)
sevpea <- sapply(as.data.frame(evpea), sd)
qevpea <- nFactors::moreStats(evpea, quantile = quantile)[3, ]
sqevpea <- sevpea
sqevpea <- sapply(as.data.frame(sqevpea), SEcentile, n = rep,
p = cent)
result <- list(eigen = data.frame(mevpea, sevpea, qevpea,
sqevpea),
subject = r,
variables = c,
centile = cent)
class(result) <- "parallel"
return(result)
}


cor <- qgraph::cor_auto(df)

ap <- parallel(subject=nrow(df), var=ncol(df))
nS <- nFactors::nScree(x=eigen(cor)$values, aparallel=ap$eigen$qevpea)

# Eigeinvalues data
eigenvalues <- nS$Analysis %>%
dplyr::select_("Eigenvalues",
"Exp.Variance"="Prop",
"Cum.Variance"="Cumu") %>%
mutate_("n.Factors"= ~1:nrow(nS$Analysis))


# Processing
# -------------------
results <- data.frame(Method=c("Optimal Coordinates",
"Acceleration Factor",
"Parallel Analysis",
"Eigenvalues (Kaiser Criterion)"),
n_optimal=as.numeric(nS$Components[1,]))


vss <- psych::VSS(cor,
n=n_max,
n.obs=nrow(df),
rotate=rotate,
fm=fm, plot=F) # fm can be "pa", "pc", "minres", "mle"
stats <- vss$vss.stats
stats$map <- vss$map
stats$n_factors <- 1:nrow(stats)

results2 <- data.frame(Method=c("Velicer MAP",
"BIC",
"Sample Size Adjusted BIC"),
n_optimal=c(na.omit(stats[stats$map==min(stats$map, na.rm = T),])$n_factors,
na.omit(stats[stats$BIC==min(stats$BIC, na.rm = T),])$n_factors,
na.omit(stats[stats$SABIC==min(stats$SABIC, na.rm = T),])$n_factors))
results <- rbind(results, results2)


cfits <- vss[grep("cfit", names(vss))]
for (name in names(cfits)){
cfit <- cfits[[name]]

cfit <- data.frame(cfit=cfit, n_factors=1:length(cfit))

result3 <- data.frame(Method=c(gsub("cfit.", "VSS Complexity ", name)),
n_optimal=c(na.omit(cfit[cfit$cfit==max(cfit$cfit, na.rm = T),])$n_factors))

results <- rbind(results, result3)
}


eigenvalues <- results %>%
group_by_("n_optimal") %>%
summarise_("n_method"=~n()) %>%
mutate_("n_optimal"=~factor(n_optimal, levels=1:nrow(eigenvalues))) %>%
complete_("n_optimal", fill=list(n_method = 0)) %>%
arrange_("n_optimal") %>%
rename_("n.Factors"="n_optimal",
"n.Methods"="n_method") %>%
mutate_("n.Factors"=~as.integer(n.Factors)) %>%
left_join(eigenvalues, by="n.Factors")


# Values
# -------------
values <- list(eigenvalues=eigenvalues, methods=results)

# Summary
# -------------
summary <- eigenvalues

# Text
# -------------
text <- "Not implemented yet :("


# Plot
# -------------
plot_data <- eigenvalues
plot_data$n.Methods.Ratio <- plot_data$n.Methods/sum(plot_data$n.Methods)
plot_data$n.Methods.Ratio <- plot_data$n.Methods.Ratio*(1/max(plot_data$n.Methods.Ratio))
plot_data$area <- plot_data$n.Methods.Ratio/(max(plot_data$n.Methods.Ratio) / max(plot_data$Eigenvalues))
plot_data$var <- plot_data$Cum.Variance/(max(plot_data$Cum.Variance) / max(plot_data$Eigenvalues))

plot <- plot_data %>%
ggplot(aes_string(x="n.Factors", y="Eigenvalues")) +
geom_area(aes_string(y="area"),
fill="#FFC107",
alpha=0.5) +
geom_line(colour="#E91E63",
size=1) +
geom_hline(yintercept = 1, linetype="dashed", colour="#607D8B") +
geom_line(aes_string(y = "var"),
colour="#2196F3",
size=1) +
scale_y_continuous(sec.axis = sec_axis(trans= ~.*(max(eigenvalues$Cum.Variance) / max(eigenvalues$Eigenvalues)),
name = 'Cumulative Variance\n')) +
ylab("Eigenvalues\n") +
xlab("\nNumber of Factors") +
theme_minimal()
plot

# Output
# -------------
output <- list(text = text, plot = plot, summary = summary, values = values)

class(output) <- c("psychobject", "list")
return(output)

}
39 changes: 39 additions & 0 deletions man/n_factors.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions tests/testthat/test-n_factors.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
context("n_factors")

test_that("Correct Value", {
results <- attitude %>%
select_if(is.numeric) %>%
psycho::n_factors()

testthat::expect_equal(nrow(summary(results)), 7)
testthat::expect_equal(nrow(psycho::values(results)$methods), 9)
testthat::expect_equal(length(plot(results)), 9)

})
38 changes: 37 additions & 1 deletion vignettes/overview.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ author:
date: "`r Sys.Date()`"
tags: [r, psychology, neuroscience]
abstract: |
Psycho is an R package that aims at providing tools for psychologists, neuropsychologists and neuroscientists, to transform statistical outputs into something readable that can be, almost directly, copied and pasted into a report. It also implements various functions useful in psychological science, such as correlation matrices, assessment plot creation or normalization. The package revolves around the psychobject. Main functions from the package return this type, and the analyze() function transforms other R objects (for now, only stan_lmer type) into psychobjects. Four functions can then be applied on a psychobject: summary(), print(), plot() and values(). Contrary to many other packages which goal is to produce statistical analyzes, `psycho`'s goal is to fill the gap between statistical R output and statistical report writing, with a focus on APA formatting guidelines. Complex outputs, such as those of Bayesian linear models, are automatically transformed into readable text, important values are extracted and plots are drawn to illustrate the effects. Thus, the results can easily be incorporated into shareable reports and publications, saving time and preventing errors for better, reproducible, science.
Psycho is an R package that aims at providing tools for psychologists, neuropsychologists and neuroscientists, to transform statistical outputs into something readable that can be, almost directly, copied and pasted into a report. It also implements various functions useful in psychological science, such as correlation matrices, assessment plot creation or normalization. The package revolves around the psychobject. Main functions from the package return this type, and the `analyze()` function transforms other R objects into psychobjects. Four functions can then be applied on a psychobject: `summary()`, `print()`, `plot()` and `values()`. Contrary to many other packages which goal is to produce statistical analyzes, `psycho` aims at filling the gap between statistical R outputs and statistical report writing, with a focus on APA formatting guidelines, to enhance the standardization of results reporting. Complex outputs, such as those of Bayesian and frequentist mixed models, are automatically transformed into readable text, tables, and plots that illustrate the effects. Thus, the results can easily be incorporated into shareable reports and publications, promoting data exploration, saving time and preventing errors for better, reproducible, science.
vignette: >
%\VignetteIndexEntry{Overview}
%\VignetteEngine{knitr::rmarkdown}
Expand Down Expand Up @@ -149,7 +149,43 @@ print(results)
plot(results)
```

------

## How many factors/components to retain?

The `n_factors()` function is useful in before running principal component (PCA) or factor (FA) analysis. As many statistical methods exists to that purpose, this function gathers them together and gives an overview on the most frequent result. It also draw a nice plot with the eigenvalues and the proportion of explained variance.


```{r echo=FALSE, message=FALSE, warning=FALSE, results='hide'}
results <- attitude %>%
select_if(is.numeric) %>%
psycho::n_factors()
# Get a summary
summary(results)
```

```{r echo=FALSE, message=FALSE, warning=FALSE}
kable(summary(results))
```

We can also extract the final result (the optimal number of factors) for each method:

```{r echo=FALSE, message=FALSE, warning=FALSE, results='hide'}
psycho::values(results)$methods
```

```{r echo=FALSE, message=FALSE, warning=FALSE}
kable(psycho::values(results)$methods)
```

And, of course, plot it :)

```{r, fig.width=7, fig.height=4.5, eval = TRUE, results='markup', fig.align='center'}
plot(results)
```
------

## Analyze the Mixed-Modelling Framework
Expand Down
170 changes: 144 additions & 26 deletions vignettes/overview.html

Large diffs are not rendered by default.

Binary file not shown.

1 comment on commit 458d54f

@lintr-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R/n_factors.R:57:16: style: Put spaces around all infix operators.

return(sd/sqrt(n) * sqrt(p * (1 - p))/dnorm(qnorm(p)))
              ~^~

R/n_factors.R:57:44: style: Put spaces around all infix operators.

return(sd/sqrt(n) * sqrt(p * (1 - p))/dnorm(qnorm(p)))
                                          ~^~

R/n_factors.R:77:25: style: Put spaces around all infix operators.

ap <- parallel(subject=nrow(df), var=ncol(df))
                       ~^~

R/n_factors.R:77:39: style: Put spaces around all infix operators.

ap <- parallel(subject=nrow(df), var=ncol(df))
                                     ~^~

R/n_factors.R:78:27: style: Put spaces around all infix operators.

nS <- nFactors::nScree(x=eigen(cor)$values, aparallel=ap$eigen$qevpea)
                         ~^~

R/n_factors.R:78:56: style: Put spaces around all infix operators.

nS <- nFactors::nScree(x=eigen(cor)$values, aparallel=ap$eigen$qevpea)
                                                      ~^~

R/n_factors.R:83:33: style: Put spaces around all infix operators.

"Exp.Variance"="Prop",
                               ~^~

R/n_factors.R:84:33: style: Put spaces around all infix operators.

"Cum.Variance"="Cumu") %>%
                               ~^~

R/n_factors.R:85:24: style: Put spaces around all infix operators.

​    mutate_("n.Factors"= ~1:nrow(nS$Analysis))
                      ~^

R/n_factors.R:90:31: style: Put spaces around all infix operators.

results <- data.frame(Method=c("Optimal Coordinates",
                             ~^~

R/n_factors.R:94:34: style: Put spaces around all infix operators.

n_optimal=as.numeric(nS$Components[1,]))
                                ~^~

R/n_factors.R:98:22: style: Put spaces around all infix operators.

n=n_max,
                    ~^~

R/n_factors.R:99:26: style: Put spaces around all infix operators.

n.obs=nrow(df),
                        ~^~

R/n_factors.R:100:27: style: Put spaces around all infix operators.

rotate=rotate,
                         ~^~

R/n_factors.R:101:23: style: Put spaces around all infix operators.

fm=fm, plot=F)  # fm can be "pa", "pc", "minres", "mle"
                     ~^~

R/n_factors.R:101:32: style: Put spaces around all infix operators.

fm=fm, plot=F)  # fm can be "pa", "pc", "minres", "mle"
                              ~^~

R/n_factors.R:106:32: style: Put spaces around all infix operators.

results2 <- data.frame(Method=c("Velicer MAP",
                              ~^~

R/n_factors.R:109:1: style: lines should not be more than 80 characters.

n_optimal=c(na.omit(stats[stats$map==min(stats$map, na.rm = T),])$n_factors,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:109:35: style: Put spaces around all infix operators.

n_optimal=c(na.omit(stats[stats$map==min(stats$map, na.rm = T),])$n_factors,
                                 ~^~

R/n_factors.R:109:61: style: Put spaces around all infix operators.

n_optimal=c(na.omit(stats[stats$map==min(stats$map, na.rm = T),])$n_factors,
                                                           ~^~~

R/n_factors.R:110:1: style: lines should not be more than 80 characters.

​                                     na.omit(stats[stats$BIC==min(stats$BIC, na.rm = T),])$n_factors,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:110:61: style: Put spaces around all infix operators.

​                                     na.omit(stats[stats$BIC==min(stats$BIC, na.rm = T),])$n_factors,
                                                           ~^~~

R/n_factors.R:111:1: style: lines should not be more than 80 characters.

​                                     na.omit(stats[stats$SABIC==min(stats$SABIC, na.rm = T),])$n_factors))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:111:63: style: Put spaces around all infix operators.

​                                     na.omit(stats[stats$SABIC==min(stats$SABIC, na.rm = T),])$n_factors))
                                                             ~^~~

R/n_factors.R:119:28: style: Put spaces around all infix operators.

cfit <- data.frame(cfit=cfit, n_factors=1:length(cfit))
                          ~^~

R/n_factors.R:119:44: style: Put spaces around all infix operators.

cfit <- data.frame(cfit=cfit, n_factors=1:length(cfit))
                                          ~^~

R/n_factors.R:121:33: style: Put spaces around all infix operators.

result3 <- data.frame(Method=c(gsub("cfit.", "VSS Complexity ", name)),
                               ~^~

R/n_factors.R:122:1: style: lines should not be more than 80 characters.

n_optimal=c(na.omit(cfit[cfit$cfit==max(cfit$cfit, na.rm = T),])$n_factors))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:122:36: style: Put spaces around all infix operators.

n_optimal=c(na.omit(cfit[cfit$cfit==max(cfit$cfit, na.rm = T),])$n_factors))
                                  ~^~

R/n_factors.R:122:61: style: Put spaces around all infix operators.

n_optimal=c(na.omit(cfit[cfit$cfit==max(cfit$cfit, na.rm = T),])$n_factors))
                                                           ~^~~

R/n_factors.R:130:26: style: Put spaces around all infix operators.

​    summarise_("n_method"=~n()) %>%
                        ~^~

R/n_factors.R:131:24: style: Put spaces around all infix operators.

​    mutate_("n_optimal"=~factor(n_optimal, levels=1:nrow(eigenvalues))) %>%
                      ~^~

R/n_factors.R:131:50: style: Put spaces around all infix operators.

​    mutate_("n_optimal"=~factor(n_optimal, levels=1:nrow(eigenvalues))) %>%
                                                ~^~

R/n_factors.R:132:32: style: Put spaces around all infix operators.

​    complete_("n_optimal", fill=list(n_method = 0)) %>%
                              ~^~

R/n_factors.R:134:24: style: Put spaces around all infix operators.

​    rename_("n.Factors"="n_optimal",
                      ~^~

R/n_factors.R:135:23: style: Put spaces around all infix operators.

"n.Methods"="n_method") %>%
                     ~^~

R/n_factors.R:136:24: style: Put spaces around all infix operators.

​    mutate_("n.Factors"=~as.integer(n.Factors)) %>%
                      ~^~

R/n_factors.R:137:30: style: Put spaces around all infix operators.

​    left_join(eigenvalues, by="n.Factors")
                            ~^~

R/n_factors.R:142:29: style: Put spaces around all infix operators.

values <- list(eigenvalues=eigenvalues, methods=results)
                           ~^~

R/n_factors.R:142:50: style: Put spaces around all infix operators.

values <- list(eigenvalues=eigenvalues, methods=results)
                                                ~^~

R/n_factors.R:156:51: style: Put spaces around all infix operators.

plot_data$n.Methods.Ratio <- plot_data$n.Methods/sum(plot_data$n.Methods)
                                                 ~^~

R/n_factors.R:157:1: style: lines should not be more than 80 characters.

plot_data$n.Methods.Ratio <- plot_data$n.Methods.Ratio*(1/max(plot_data$n.Methods.Ratio))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:157:57: style: Put spaces around all infix operators.

plot_data$n.Methods.Ratio <- plot_data$n.Methods.Ratio*(1/max(plot_data$n.Methods.Ratio))
                                                       ~^~

R/n_factors.R:157:60: style: Put spaces around all infix operators.

plot_data$n.Methods.Ratio <- plot_data$n.Methods.Ratio*(1/max(plot_data$n.Methods.Ratio))
                                                          ~^~

R/n_factors.R:158:1: style: lines should not be more than 80 characters.

plot_data$area <- plot_data$n.Methods.Ratio/(max(plot_data$n.Methods.Ratio) / max(plot_data$Eigenvalues))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:158:46: style: Put spaces around all infix operators.

plot_data$area <- plot_data$n.Methods.Ratio/(max(plot_data$n.Methods.Ratio) / max(plot_data$Eigenvalues))
                                            ~^~

R/n_factors.R:159:1: style: lines should not be more than 80 characters.

plot_data$var <- plot_data$Cum.Variance/(max(plot_data$Cum.Variance) / max(plot_data$Eigenvalues))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:159:42: style: Put spaces around all infix operators.

plot_data$var <- plot_data$Cum.Variance/(max(plot_data$Cum.Variance) / max(plot_data$Eigenvalues))
                                        ~^~

R/n_factors.R:162:24: style: Put spaces around all infix operators.

​    ggplot(aes_string(x="n.Factors", y="Eigenvalues")) +
                      ~^~

R/n_factors.R:162:39: style: Put spaces around all infix operators.

​    ggplot(aes_string(x="n.Factors", y="Eigenvalues")) +
                                     ~^~

R/n_factors.R:163:27: style: Put spaces around all infix operators.

​    geom_area(aes_string(y="area"),
                         ~^~

R/n_factors.R:164:19: style: Put spaces around all infix operators.

fill="#FFC107",
                 ~^~

R/n_factors.R:165:20: style: Put spaces around all infix operators.

alpha=0.5) +
                  ~^~

R/n_factors.R:166:21: style: Put spaces around all infix operators.

​    geom_line(colour="#E91E63",
                   ~^~

R/n_factors.R:167:19: style: Put spaces around all infix operators.

size=1) +
                 ~^~

R/n_factors.R:168:40: style: Put spaces around all infix operators.

​    geom_hline(yintercept = 1, linetype="dashed", colour="#607D8B") +
                                      ~^~

R/n_factors.R:168:57: style: Put spaces around all infix operators.

​    geom_hline(yintercept = 1, linetype="dashed", colour="#607D8B") +
                                                       ~^~

R/n_factors.R:170:21: style: Put spaces around all infix operators.

colour="#2196F3",
                   ~^~

R/n_factors.R:171:19: style: Put spaces around all infix operators.

size=1) +
                 ~^~

R/n_factors.R:172:1: style: lines should not be more than 80 characters.

​    scale_y_continuous(sec.axis = sec_axis(trans= ~.*(max(eigenvalues$Cum.Variance) / max(eigenvalues$Eigenvalues)),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

R/n_factors.R:172:49: style: Put spaces around all infix operators.

​    scale_y_continuous(sec.axis = sec_axis(trans= ~.*(max(eigenvalues$Cum.Variance) / max(eigenvalues$Eigenvalues)),
                                               ~^

R/n_factors.R:172:53: style: Put spaces around all infix operators.

​    scale_y_continuous(sec.axis = sec_axis(trans= ~.*(max(eigenvalues$Cum.Variance) / max(eigenvalues$Eigenvalues)),
                                                   ~^~

R/n_factors.R:173:51: style: Only use double-quotes.

name = 'Cumulative Variance\n')) +
                                                  ^~~~~~~~~~~~~~~~~~~~~~~

Please sign in to comment.