Exploratory Factor Analysis

Estimation may take a few seconds to minutes depending on the dataset.

Data

Input values must be separated by tabs. Copy and paste from Excel/Numbers.

Please make sure that your data includes the header (variable names) in the first row.


                
                

Basic statistics


                

Correlation


                
Scatter plot matrices

Scree plot

Suggested number of factors

                

Specifying the number of factors


Results of exploratory factor analysis

Maximum likelihood with promax rotation


                

Factor loadings plot (Factors 1 and 2)

Download the plot as pdf

Download the plot as pdf


R session info

              
Note

This web application is developed with Shiny.


List of Packages Used
library(shiny)
library(shinyAce)
library(psych)

Code

Source code for this application is based on "The handbook of Research in Foreign Language Learning and Teaching" (Takeuchi & Mizumoto, 2012).

The code for this web application is available at GitHub.

If you want to run this code on your computer (in a local R session), run the code below:
library(shiny)
runGitHub("efa","mizumot")


Citation in Publications

Mizumoto, A. (2015). Langtest (Version 1.0) [Web application]. Retrieved from http://langtest.jp


Article

Mizumoto, A., & Plonsky, L. (2015). R as a lingua franca: Advantages of using R for quantitative research in applied linguistics. Applied Linguistics, Advance online publication. doi:10.1093/applin/amv025


Recommended

To learn more about R, I suggest this excellent and free e-book (pdf), A Guide to Doing Statistics in Second Language Research Using R, written by Dr. Jenifer Larson-Hall.

Also, if you are a cool Mac user and want to use R with GUI, MacR is defenitely the way to go!


Author

Atsushi MIZUMOTO, Ph.D.
Associate Professor of Applied Linguistics
Faculty of Foreign Language Studies /
Graduate School of Foreign Language Education and Research,
Kansai University, Osaka, Japan



Code for "Exploratory Factor Analysis"
by Atsushi Mizumoto

show with app
library(shiny)
library(shinyAce)
library(psych)



shinyServer(function(input, output) {
    
    
    
    bs <- reactive({
        x <- read.csv(text=input$text, sep="\t")
        describe(x)[2:13]
    })
    
    
    
    correl <- reactive({
        x <- read.csv(text=input$text, sep="\t")
        round(cor(cbind(x), use = "complete"),3)
    })
    
    
    
    makecorPlot <- function(){
        x <- read.csv(text=input$text, sep="\t")
        pairs.panels(x)
    }
    
    output$corPlot <- renderPlot({
        print(makecorPlot())
    })


    
    
    sp <- reactive({
    
        dat <- read.csv(text=input$text, sep="\t")
    
        sp <- fa.parallel(dat)
        
        list(sp = sp) #他で使用するため
    })



    
    output$makesPlot <- renderPlot({
        dat <- read.csv(text=input$text, sep="\t")
        fa.parallel(dat)
    })
   
   

    nf <- reactive({
    
        #dat <- read.csv(text=input$text, sep="\t")
        #res <- fa.parallel(dat)
        
        facno <- sp()$sp[[6]]
        compono <- sp()$sp[[7]]
        fa.val <- round(sp()$sp[[1]],2)
        pc.val <- round(sp()$sp[[3]],2)
        
        cat(" Parallel analysis suggests that the number of factors =", facno, "\n",
            "and the number of components =", compono, "\n",
            "\n",
            "Eigen values of original factors:", "\n",
            fa.val,"\n","\n",
            "Eigen values of Original components:", "\n",
            pc.val)
    })
    
    
    
    efaresult <- reactive({
        
        dat <- read.csv(text=input$text, sep="\t")
        
    # ここからパラレルの場合(デフォルト)
        if (input$numfactor == "parallel") {


        # factanal 関数の結果を整形して表示する
        # http://aoki2.si.gunma-u.ac.jp/R/src/factanal2.R
        factanal2 <- function(	dat,							# データ行列
        factors=0,						# 抽出する因子数
        rotation=c("promax", "varimax", "none"),		# 因子軸の回転法
        scores=c("none", "regression", "Bartlett"),		# 因子得点の算出法
        verbose=TRUE)						# 結果の画面表示をするかどうか
        {
            p <- ncol(dat)								# 変数の個数
            n <- nrow(dat)								# 行数(欠損値を含むケースも含む)
            if (is.null(colnames(dat))) colnames(dat) <- paste("Var", 1:p, sep=".")	# 変数名がないときにデフォルト名をつける
            if (is.null(rownames(dat))) rownames(dat) <- paste("Case", 1:n, sep="-")# 行名がないときにデフォルト名をつける
            dat <- subset(dat, complete.cases(dat))					# 欠損値を持つケースを除く
            rotation <- match.arg(rotation)						# 引数の補完
            scores <- match.arg(scores)						# 引数の補完
            
            if (factors == 0) {							# 抽出因子数が指定されないときは,
                factors <- max(1, floor((2*p+1-sqrt((2*p+1)^2-4*(p^2-p)))/2))	# デフォルトの因子数
            }
            result<-factanal(dat, factors=factors, rotation=rotation, scores=scores)# 関数呼び出し
            Communality <- 1-result$uniquenesses					# 共通性は,斜交回転のときには因子負荷量の二乗和ではない
            result$cosmetic <- cbind(result$loadings, Communality)			# 共通性を付加
            if (rotation!="promax") {						# 斜交回転でない場合には,
                SS.loadings <- colSums(result$loadings^2)			# 因子負荷量の二乗和
                SS.loadings <- c(SS.loadings, sum(SS.loadings))			# 総和を加える
                Proportion <- SS.loadings/p*100					# 寄与率
                Cum.Prop. <- cumsum(Proportion)					# 累積寄与率
                Cum.Prop.[factors+1] <- NA
                result$cosmetic <- rbind(result$cosmetic, SS.loadings, Proportion, Cum.Prop.)
            }
            if (verbose == TRUE) {							# 画面表示をするとき
                if (result$dof) {						# モデル適合度の自由度が 0 でないとき
                    test <- data.frame(result$STATISTIC, result$dof, result$PVAL)
                    colnames(test) <- c("Chi sq.", "d.f.", "P value")
                    rownames(test) <- ""
                    cat(sprintf("H0: %i factors are sufficient.\n", factors))
                    print(test)
                }
                else {								# 自由度が 0 になるとき
                    cat(sprintf("The degrees of freedom for the model is 0 and the fit was %g\n", result$criteria[1]))
                }
                #cat(sprintf("\nFactor loadings(rotation:%s)\n", rotation))	# 因子負荷量
                #print(result$cosmetic)
                #if (scores != "none") {
                #cat(sprintf("\nFactor scores(%s)\n", scores))		# 因子得点
                #print(result$scores)
                #}
            }
            invisible(result)							# 明示的に print しないと,何も出力しない
        }
        
        suggested <- sp()$sp[[6]]
        
        efa <- factanal2(dat, factors=suggested, rotation="promax")
        
        #list(efa = efa)
        
        
        # 因子負荷量の大きさの順に変数を並べ替える
        # http://aoki2.si.gunma-u.ac.jp/R/src/sort.loadings.R
        sort.loadings <- function(x)					# factanalが返すオブジェクト
        {
            a <- x$loadings
            y <- abs(a)						# 因子負荷量の絶対値
            z <- apply(y, 1, which.max)				# 各変数をどの因子に含めるべきか
            loadings <- NULL					# 結果
            for (i in 1:ncol(y)) {
                b <- a[z == i,, drop=FALSE]
                if (nrow(b)) {
                    t <- order(b[, i, drop=FALSE], decreasing=TRUE)	# 因子単位で並べ替え情報を得る
                    loadings <- rbind(loadings, b[t,, drop=FALSE])
                }
            }
            class(loadings) <- "loadings"				# クラスの設定
            return(loadings)					# 結果を返す
        }


        print(sort.loadings(efa), cutoff=0)
        cat("\n")
        cat("Factor correlation:", "\n")
        
        if (ncol(efa$loadings) == 1) {
            
            c("No factor correlation available")
            
        } else {

        
        # プロマックス解の因子間相関係数行列
        # http://aoki2.si.gunma-u.ac.jp/R/src/factor.correlation.R
        factor.correlation <- function(x, factors, ...)
        {
            ans <- factanal(x, factors, rotation="none", ...)		# 回転を行わない結果を求める
            ans2 <- promax(ans$loadings)				# プロマックス回転による結果を求める
            name <- colnames(ans2$loadings)				# 名前の保存
            o <- order(colSums(ans2$loadings^2), decreasing=TRUE)	# SS loadings の大きい順
            ans2$loadings <- ans2$loadings[, o]				# loadings の並べ替え(行)
            colnames(ans2$loadings) <- name				# 名前の付け替え
            class(ans2$loadings) <- "loadings"				# class がなくなるので再設定
            ans2$rotmat <- ans2$rotmat[o, o]				# rotmat の並べ替え(行・列)
            ans3 <- ans2$rotmat						# 回転行列を取り出す
            r <- solve(t(ans3) %*% ans3)				# 因子間相関係数行列を計算する
            colnames(r) <- rownames(r) <- name				# 名前を付ける(必須ではない)
            r <- round(r, 3)
            return(r)			# プロマックス解と因子間相関係数行列
        }
        
        factor.correlation(~., data=dat, suggested)
        
        }
        
    # ここまでパラレルの場合(デフォルト)
    } else { # ここから因子数指定の場合
        
        # factanal 関数の結果を整形して表示する
        # http://aoki2.si.gunma-u.ac.jp/R/src/factanal2.R
        factanal2 <- function(	dat,							# データ行列
        factors=0,						# 抽出する因子数
        rotation=c("promax", "varimax", "none"),		# 因子軸の回転法
        scores=c("none", "regression", "Bartlett"),		# 因子得点の算出法
        verbose=TRUE)						# 結果の画面表示をするかどうか
        {
            p <- ncol(dat)								# 変数の個数
            n <- nrow(dat)								# 行数(欠損値を含むケースも含む)
            if (is.null(colnames(dat))) colnames(dat) <- paste("Var", 1:p, sep=".")	# 変数名がないときにデフォルト名をつける
            if (is.null(rownames(dat))) rownames(dat) <- paste("Case", 1:n, sep="-")# 行名がないときにデフォルト名をつける
            dat <- subset(dat, complete.cases(dat))					# 欠損値を持つケースを除く
            rotation <- match.arg(rotation)						# 引数の補完
            scores <- match.arg(scores)						# 引数の補完
            
            if (factors == 0) {							# 抽出因子数が指定されないときは,
                factors <- max(1, floor((2*p+1-sqrt((2*p+1)^2-4*(p^2-p)))/2))	# デフォルトの因子数
            }
            result<-factanal(dat, factors=factors, rotation=rotation, scores=scores)# 関数呼び出し
            Communality <- 1-result$uniquenesses					# 共通性は,斜交回転のときには因子負荷量の二乗和ではない
            result$cosmetic <- cbind(result$loadings, Communality)			# 共通性を付加
            if (rotation!="promax") {						# 斜交回転でない場合には,
                SS.loadings <- colSums(result$loadings^2)			# 因子負荷量の二乗和
                SS.loadings <- c(SS.loadings, sum(SS.loadings))			# 総和を加える
                Proportion <- SS.loadings/p*100					# 寄与率
                Cum.Prop. <- cumsum(Proportion)					# 累積寄与率
                Cum.Prop.[factors+1] <- NA
                result$cosmetic <- rbind(result$cosmetic, SS.loadings, Proportion, Cum.Prop.)
            }
            if (verbose == TRUE) {							# 画面表示をするとき
                if (result$dof) {						# モデル適合度の自由度が 0 でないとき
                    test <- data.frame(result$STATISTIC, result$dof, result$PVAL)
                    colnames(test) <- c("Chi sq.", "d.f.", "P value")
                    rownames(test) <- ""
                    cat(sprintf("H0: %i factors are sufficient.\n", factors))
                    print(test)
                }
                else {								# 自由度が 0 になるとき
                    cat(sprintf("The degrees of freedom for the model is 0 and the fit was %g\n", result$criteria[1]))
                }
                #cat(sprintf("\nFactor loadings(rotation:%s)\n", rotation))	# 因子負荷量
                #print(result$cosmetic)
                #if (scores != "none") {
                #cat(sprintf("\nFactor scores(%s)\n", scores))		# 因子得点
                #print(result$scores)
                #}
            }
            invisible(result)							# 明示的に print しないと,何も出力しない
        }
        
        nfact <- input$numspec # 因子数
        
        efa <- factanal2(dat, factors=nfact, rotation="promax")
        
        #list(efa = efa)
        
        
        # 因子負荷量の大きさの順に変数を並べ替える
        # http://aoki2.si.gunma-u.ac.jp/R/src/sort.loadings.R
        sort.loadings <- function(x)					# factanalが返すオブジェクト
        {
            a <- x$loadings
            y <- abs(a)						# 因子負荷量の絶対値
            z <- apply(y, 1, which.max)				# 各変数をどの因子に含めるべきか
            loadings <- NULL					# 結果
            for (i in 1:ncol(y)) {
                b <- a[z == i,, drop=FALSE]
                if (nrow(b)) {
                    t <- order(b[, i, drop=FALSE], decreasing=TRUE)	# 因子単位で並べ替え情報を得る
                    loadings <- rbind(loadings, b[t,, drop=FALSE])
                }
            }
            class(loadings) <- "loadings"				# クラスの設定
            return(loadings)					# 結果を返す
        }
        
        
        print(sort.loadings(efa), cutoff=0)
        cat("\n")
        cat("Factor correlation:", "\n")
        
        if (ncol(efa$loadings) == 1) {
            
            c("No factor correlation available")
            
        } else {


        # プロマックス解の因子間相関係数行列
        # http://aoki2.si.gunma-u.ac.jp/R/src/factor.correlation.R
        factor.correlation <- function(x, factors, ...)
        {
            ans <- factanal(x, factors, rotation="none", ...)		# 回転を行わない結果を求める
            ans2 <- promax(ans$loadings)				# プロマックス回転による結果を求める
            name <- colnames(ans2$loadings)				# 名前の保存
            o <- order(colSums(ans2$loadings^2), decreasing=TRUE)	# SS loadings の大きい順
            ans2$loadings <- ans2$loadings[, o]				# loadings の並べ替え(行)
            colnames(ans2$loadings) <- name				# 名前の付け替え
            class(ans2$loadings) <- "loadings"				# class がなくなるので再設定
            ans2$rotmat <- ans2$rotmat[o, o]				# rotmat の並べ替え(行・列)
            ans3 <- ans2$rotmat						# 回転行列を取り出す
            r <- solve(t(ans3) %*% ans3)				# 因子間相関係数行列を計算する
            colnames(r) <- rownames(r) <- name				# 名前を付ける(必須ではない)
            r <- round(r, 3)
            return(r)			# プロマックス解と因子間相関係数行列
        }
        
        factor.correlation(~., data=dat, nfact)
        }
    
    } # ここまで因子数指定の場合

    })
    
    
    
    plotInput <- renderPlot({
        
        dat <- read.csv(text=input$text, sep="\t")
        
        if (input$numfactor == "prallel") {
            
            suggested <- sp()$sp[[6]]
            efa <- factanal(dat, factors=suggested, rotation="promax")
            
        } else {
            
            nfact <- input$numspec # 因子数
            efa <- factanal(dat, factors=nfact, rotation="promax")
        }
        
        
        if (ncol(efa$loadings) == 1) {
            
            barplot(efa$loadings[,1], main="Factor 1", ylim=c(0,1))
            
        } else {
            
            par(mfrow = c(2, 1))   # グラフを横に2つ並べる
            barplot(efa$loadings[,1], main="Factor 1", ylim=c(0,1))
            barplot(efa$loadings[,2], main="Factor 2", ylim=c(0,1))
            
        }
    })
    
    
    
    makePlot1 <- function() {
        dat <- read.csv(text=input$text, sep="\t")
        
        if (input$numfactor == "parallel") {
            
            suggested <- sp()$sp[[6]]
            efa <- factanal(dat, factors=suggested, rotation="promax")
            
        } else {
            
            nfact <- input$numspec # 因子数
            efa <- factanal(dat, factors=nfact, rotation="promax")
        }
        
        
        if (ncol(efa$loadings) == 1) {
            
            barplot(efa$loadings[,1], main="Factor 1", ylim=c(0,1))
            
        } else {
            
            par(mfrow = c(2, 1))   # グラフを横に2つ並べる
            barplot(efa$loadings[,1], main="Factor 1", ylim=c(0,1))
            barplot(efa$loadings[,2], main="Factor 2", ylim=c(0,1))
            
        }
    }



    output$facPlot1 <- renderPlot({
        print(makePlot1())
    })
    
    
    
    makePlot2 <- function() {
        dat <- read.csv(text=input$text, sep="\t")
        
        sp <- fa.parallel(dat) # ここを入れた

        if (input$numfactor == "parallel") {
            
            suggested <- sp()$sp[[6]]
            efa <- factanal(dat, factors=suggested, rotation="promax")
            
            if (ncol(efa$loadings) >= 2) {
                
                plot(efa$loadings[,1:2], type="n", xlim=c(-1,1), ylim=c(-1,1))
                text(efa$loadings[,1:2], colnames(dat))
                abline(v=0, lty=3) #0で縦に線を引き,破線(lty=3)を引く
                abline(h=0, lty=3) #0で横に線を引き,破線(lty=3)を引く
            }
            
        } else {
            
            nfact <- input$numspec # 因子数
            efa <- factanal(dat, factors=nfact, rotation="promax")
            
            if (ncol(efa$loadings) >= 2) {
                
                par(mfrow = c(1, 1))   # グラフを横に2つ並べる
                plot(efa$loadings[,1:2], type="n", xlim=c(-1,1), ylim=c(-1,1))
                text(efa$loadings[,1:2], colnames(dat))
                abline(v=0, lty=3) #0で縦に線を引き,破線(lty=3)を引く
                abline(h=0, lty=3) #0で横に線を引き,破線(lty=3)を引く
            }
        }
    }
    
    
    output$facPlot2 <- renderPlot({
        print(makePlot2())
    })
    
    
    
    
    info <- reactive({
        info1 <- paste("This analysis was conducted with ", strsplit(R.version$version.string, " \\(")[[1]][1], ".", sep = "")# バージョン情報
        info2 <- paste("It was executed on ", date(), ".", sep = "")# 実行日時
        cat(sprintf(info1), "\n")
        cat(sprintf(info2), "\n")
    })
    
    output$info.out <- renderPrint({
        info()
    })





    output$textarea.out <- renderPrint({
        bs()
    })

    output$correl.out <- renderPrint({
        correl()
    })
    
    output$nf.out <- renderPrint({
        nf()
    })
    
    output$efaresult.out <- renderPrint({
        efaresult()
    })
    
    output$check <- renderTable({
        head(check(), n = 10)
    }, digits = 0)
    

})
library(shiny)
library(shinyAce)


shinyUI(bootstrapPage(


    headerPanel("Exploratory Factor Analysis"),

    mainPanel(
        tabsetPanel(

        tabPanel("Main",

            p('Estimation may take a few seconds to minutes depending on the dataset.'),

            h3("Data"),
            p('Input values must be separated by tabs. Copy and paste from Excel/Numbers.'),
            p(HTML("<b><div style='background-color:#FADDF2;border:1px solid black;'>Please make sure that your data includes the header (variable names) in the first row.</div></b>")),

            aceEditor("text", value="item1\titem2\titem3\titem4\titem5\titem6\titem7\titem8\n7\t6\t6\t6\t7\t6\t6\t7\n5\t5\t6\t7\t6\t5\t5\t4\n7\t6\t5\t7\t6\t6\t6\t6\n3\t3\t3\t5\t4\t4\t3\t3\n6\t4\t5\t5\t5\t4\t5\t4\n5\t4\t4\t7\t6\t4\t6\t4\n6\t7\t6\t6\t7\t5\t5\t6\n7\t7\t7\t7\t4\t4\t4\t4\n5\t6\t4\t5\t4\t2\t2\t4\n7\t5\t6\t7\t6\t4\t5\t6\n6\t4\t4\t6\t3\t2\t2\t4\n6\t5\t4\t5\t5\t4\t4\t2\n7\t6\t5\t6\t7\t6\t6\t6\n6\t5\t7\t7\t5\t4\t4\t4\n6\t2\t1\t5\t2\t2\t2\t2\n4\t4\t5\t5\t5\t3\t3\t2\n5\t6\t4\t7\t5\t3\t3\t5\n5\t6\t5\t6\t6\t6\t5\t5\n5\t7\t6\t6\t6\t3\t4\t4\n4\t5\t4\t5\t5\t2\t3\t3\n7\t7\t2\t4\t7\t1\t1\t1\n5\t6\t5\t6\t5\t3\t4\t5\n5\t5\t5\t5\t7\t4\t4\t4\n4\t5\t2\t5\t6\t5\t5\t5\n6\t6\t6\t7\t6\t7\t7\t4\n6\t5\t3\t6\t4\t3\t4\t4\n5\t5\t5\t6\t5\t4\t5\t5\n6\t7\t6\t7\t7\t5\t6\t7\n5\t5\t4\t6\t5\t4\t4\t5\n6\t4\t7\t7\t7\t6\t5\t5\n6\t6\t4\t6\t6\t6\t6\t5\n5\t5\t3\t4\t4\t4\t4\t5\n6\t6\t6\t6\t6\t5\t5\t5\n5\t6\t4\t5\t4\t3\t4\t6\n4\t4\t4\t5\t5\t5\t5\t5\n6\t7\t6\t6\t5\t5\t4\t6\n4\t7\t5\t5\t5\t4\t4\t5\n7\t7\t3\t7\t7\t7\t7\t7\n6\t7\t5\t7\t7\t6\t5\t6\n5\t5\t5\t5\t7\t5\t7\t7\n7\t2\t2\t2\t5\t1\t2\t3\n5\t5\t4\t6\t6\t4\t5\t5\n5\t5\t5\t5\t6\t5\t5\t6\n5\t4\t4\t4\t1\t1\t1\t1\n5\t7\t6\t7\t6\t4\t4\t5\n5\t6\t4\t6\t5\t3\t4\t4\n5\t5\t4\t5\t6\t4\t4\t4\n6\t4\t4\t7\t4\t4\t4\t4\n6\t6\t4\t7\t6\t4\t4\t5\n6\t7\t3\t5\t4\t3\t4\t5\n5\t6\t6\t6\t5\t4\t4\t5\n7\t7\t7\t7\t7\t7\t6\t6\n7\t6\t5\t7\t6\t5\t5\t4\n5\t5\t4\t5\t5\t3\t3\t4\n7\t6\t5\t7\t7\t5\t7\t7\n6\t6\t4\t5\t3\t2\t3\t2\n4\t4\t3\t4\t2\t1\t1\t1\n7\t7\t7\t7\t7\t6\t6\t7\n3\t5\t5\t3\t5\t4\t4\t2\n3\t2\t2\t5\t2\t2\t2\t2\n7\t6\t4\t5\t7\t6\t7\t7\n4\t7\t4\t7\t7\t7\t7\t7\n5\t5\t4\t6\t5\t4\t4\t5\n5\t5\t5\t5\t5\t3\t3\t3\n5\t4\t3\t5\t3\t2\t3\t3\n5\t4\t5\t6\t5\t3\t5\t4\n6\t6\t4\t6\t5\t4\t3\t4\n4\t6\t5\t6\t6\t6\t4\t4\n6\t7\t3\t4\t4\t2\t3\t3\n5\t4\t4\t5\t6\t5\t5\t4\n7\t7\t7\t7\t7\t7\t7\t7\n4\t3\t3\t5\t6\t5\t5\t4\n5\t7\t4\t6\t5\t4\t4\t4\n6\t6\t6\t6\t6\t5\t5\t5\n5\t5\t4\t5\t5\t4\t4\t5\n6\t5\t4\t6\t5\t4\t4\t4\n6\t3\t3\t4\t5\t4\t4\t4\n6\t7\t6\t5\t3\t3\t2\t1\n5\t5\t4\t6\t6\t5\t5\t4\n4\t6\t5\t7\t7\t6\t7\t7\n5\t5\t3\t5\t4\t3\t4\t4\n6\t4\t5\t5\t5\t4\t3\t3\n6\t7\t6\t7\t5\t2\t6\t6\n4\t7\t5\t7\t5\t3\t4\t5\n5\t4\t4\t5\t3\t3\t3\t3\n6\t5\t5\t6\t5\t4\t5\t6\n5\t4\t5\t6\t4\t3\t3\t4\n4\t3\t3\t5\t5\t3\t4\t4\n4\t6\t4\t5\t4\t2\t2\t4\n6\t5\t4\t6\t6\t4\t4\t5\n6\t6\t4\t7\t3\t2\t2\t4\n5\t4\t6\t6\t4\t1\t4\t3\n4\t5\t5\t5\t3\t3\t3\t3\n4\t6\t4\t6\t4\t4\t4\t5\n4\t4\t4\t4\t4\t3\t3\t3\n5\t5\t5\t5\t4\t3\t3\t4\n7\t5\t5\t6\t6\t5\t4\t6\n6\t6\t5\t6\t7\t6\t6\t6\n6\t6\t6\t6\t5\t6\t6\t5\n7\t5\t6\t7\t6\t3\t5\t5\n6\t6\t4\t6\t5\t4\t5\t5\n6\t6\t4\t5\t5\t4\t4\t6\n5\t5\t4\t6\t2\t2\t2\t5\n6\t7\t4\t6\t4\t4\t3\t4\n5\t5\t4\t5\t4\t4\t4\t4\n6\t5\t3\t5\t4\t3\t6\t6\n3\t7\t2\t5\t6\t5\t4\t4\n2\t5\t5\t5\t4\t3\t3\t3\n7\t6\t5\t7\t7\t6\t7\t7\n6\t6\t6\t7\t6\t6\t7\t6\n5\t3\t4\t5\t6\t5\t5\t5\n5\t3\t3\t3\t7\t2\t2\t5\n5\t5\t4\t6\t6\t2\t5\t4\n7\t6\t5\t6\t7\t7\t7\t7\n7\t5\t7\t6\t3\t4\t2\t3\n5\t4\t5\t5\t6\t6\t6\t6\n4\t6\t3\t5\t5\t3\t3\t4\n5\t4\t4\t5\t6\t5\t5\t5\n6\t6\t6\t7\t6\t4\t4\t4\n5\t7\t5\t6\t7\t6\t6\t6\n5\t6\t4\t6\t5\t4\t4\t4\n5\t4\t4\t6\t4\t4\t4\t4\n6\t7\t5\t5\t4\t3\t3\t4\n4\t6\t6\t7\t6\t3\t3\t3\n5\t5\t5\t5\t5\t5\t5\t5\n6\t4\t5\t5\t6\t4\t4\t5\n6\t6\t6\t6\t6\t4\t5\t6\n7\t7\t7\t7\t7\t7\t7\t7\n5\t3\t4\t5\t5\t3\t4\t5",
                mode="r", theme="cobalt"),

            br(),

            h3("Basic statistics"),
            verbatimTextOutput("textarea.out"),

            br(),

            h3("Correlation"),
            verbatimTextOutput("correl.out"),

            br(),

            strong("Scatter plot matrices"),

            br(),

            plotOutput("corPlot"),

            br(),

            h3("Scree plot"),

            plotOutput(outputId ="makesPlot", width="80%"),

            strong("Suggested number of factors"),
            verbatimTextOutput("nf.out"),

            br(),
            br(),

            h3("Specifying the number of factors"),

            radioButtons("numfactor", strong("Number of factors:"),
            list("Use the number of factors suggested by parallel analysis" = "parallel",
                 "Specify the number of factors" = "spec"), 'Use the number of factors suggested by parallel analysis'),
                conditionalPanel(
                    condition = "input.numfactor == 'spec'",
                    numericInput("numspec", "Number of factors:", 3)
                    ),
            br(),

            h3("Results of exploratory factor analysis"),
            p("Maximum likelihood with promax rotation"),
            verbatimTextOutput("efaresult.out"),

            br(),

            h3("Factor loadings plot (Factors 1 and 2)"),
            downloadButton('downloadPlot1', 'Download the plot as pdf'),
            plotOutput("facPlot1", height = "600px"),

            br(),

            downloadButton('downloadPlot2', 'Download the plot as pdf'),
            plotOutput("facPlot2", height = "500px"),

            br(),
            br(),

            strong('R session info'),
            verbatimTextOutput("info.out")

            ),


        tabPanel("About",

            strong('Note'),
            p('This web application is developed with',
            a("Shiny.", href="http://www.rstudio.com/shiny/", target="_blank"),
            ''),

            br(),

            strong('List of Packages Used'), br(),
            code('library(shiny)'),br(),
            code('library(shinyAce)'),br(),
            code('library(psych)'),br(),

            br(),

            strong('Code'),
            p('Source code for this application is based on',
            a('"The handbook of Research in Foreign Language Learning and Teaching" (Takeuchi & Mizumoto, 2012).', href='http://mizumot.com/handbook/', target="_blank")),

            p('The code for this web application is available at',
            a('GitHub.', href='https://github.com/mizumot/efa', target="_blank")),

            p('If you want to run this code on your computer (in a local R session), run the code below:',
            br(),
            code('library(shiny)'),br(),
            code('runGitHub("efa","mizumot")')
            ),

            br(),

            strong('Citation in Publications'),
            p('Mizumoto, A. (2015). Langtest (Version 1.0) [Web application]. Retrieved from http://langtest.jp'),

            br(),

            strong('Article'),
            p('Mizumoto, A., & Plonsky, L. (2015).', a("R as a lingua franca: Advantages of using R for quantitative research in applied linguistics.", href='http://applij.oxfordjournals.org/content/early/2015/06/24/applin.amv025.abstract', target="_blank"), em('Applied Linguistics,'), 'Advance online publication. doi:10.1093/applin/amv025'),

            br(),

            strong('Recommended'),
            p('To learn more about R, I suggest this excellent and free e-book (pdf),',
            a("A Guide to Doing Statistics in Second Language Research Using R,", href="http://cw.routledge.com/textbooks/9780805861853/guide-to-R.asp", target="_blank"),
            'written by Dr. Jenifer Larson-Hall.'),

            p('Also, if you are a cool Mac user and want to use R with GUI,',
            a("MacR", href="https://sites.google.com/site/casualmacr/", target="_blank"),
            'is defenitely the way to go!'),

            br(),

            strong('Author'),
            p(a("Atsushi MIZUMOTO,", href="http://mizumot.com", target="_blank"),' Ph.D.',br(),
            'Associate Professor of Applied Linguistics',br(),
            'Faculty of Foreign Language Studies /',br(),
            'Graduate School of Foreign Language Education and Research,',br(),
            'Kansai University, Osaka, Japan'),

            br(),

            a(img(src="http://i.creativecommons.org/p/mark/1.0/80x15.png"), target="_blank", href="http://creativecommons.org/publicdomain/mark/1.0/"),

            p(br())

            )

))
))
Code license: GPL-3