Given a data frame containing mixed variables (i.e. both categorical and continuous) like,
digits = 0:9
# set seed for reproducibility
set.seed(17)
# function to create random string
createRandString <- function(n = 5000) {
a <- do.call(paste0, replicate(5, sample(LETTERS, n, TRUE), FALSE))
paste0(a, sprintf("%04d", sample(9999, n, TRUE)), sample(LETTERS, n, TRUE))
}
df <- data.frame(ID=c(1:10), name=sample(letters[1:10]),
studLoc=sample(createRandString(10)),
finalmark=sample(c(0:100),10),
subj1mark=sample(c(0:100),10),subj2mark=sample(c(0:100),10)
)
I perform unsupervised feature selection using the package FactoMineR
df.princomp <- FactoMineR::FAMD(df, graph = FALSE)
The variable df.princomp
is a list.
Thereafter, to visualize the principal components I use
fviz_screeplot()
and fviz_contrib()
like,
#library(factoextra)
factoextra::fviz_screeplot(df.princomp, addlabels = TRUE,
barfill = "gray", barcolor = "black",
ylim = c(0, 50), xlab = "Principal Component",
ylab = "Percentage of explained variance",
main = "Principal Component (PC) for mixed variables")
factoextra::fviz_contrib(df.princomp, choice = "var",
axes = 1, top = 10, sort.val = c("desc"))
which gives the following Fig1
and Fig2
Explanation of Fig1: The Fig1 is a scree plot. A Scree Plot is a simple line segment plot that shows the fraction of total variance in the data as explained or represented by each Principal Component (PC). So we can see the first three PCs collectively are responsible for 43.8%
of total variance. The question now naturally arises, "What are these variables?". This I have shown in Fig2.
Explanation of Fig2: This figure visualizes the contribution of rows/columns from the results of Principal Component Analysis (PCA). From here I can see the variables, name
, studLoc
and finalMark
are the most important variables that can be used for further analysis.
Further Analysis- where I'm stuck at: To derive the contribution of the aforementioned variables name
, studLoc
, finalMark
. I use the principal component variable df.princomp
(see above) like df.princomp$quanti.var$contrib[,4]
and df.princomp$quali.var$contrib[,2:3]
.
I've to manually specify the column indices [,2:3]
and [,4]
.
What I want: I want to know how to do dynamic column index assignment, such that I do not have to manually code the column index [,2:3]
in the list df.princomp
?
I've already looked at the following similar questions 1, 2, 3 and 4 but cannot find my solution? Any help or suggestions to solve this problem will be helpful.
There are a lot of ways to extract contributions of individual variables to PCs. For numeric input, one can run a PCA with
prcomp
and look at$rotation
(I spoke to soon and forgot you've got factors here soprcomp
won't work directly). Since you are usingfactoextra::fviz_contrib
, it makes sense to check how that function extracts this information under the hood. Keyfactoextra::fviz_contrib
and read the function:So it's really just calling
facto_summarize
from the same package. By analogy you can do the same thing, simply call:And that's the table corresponding to your figure 2. For PC2 use
axes = 2
and so on.Regarding "how to programmatically determine the column indices of the PCs", I'm not 100% sure I understand what you want, but if you just want to say for column "finalmark", grab its contribution to PC3 you can do the following:
BTW I think
ID
in your example is treated as numeric instead of factor, but since it's just an example I'm not bothering with it.Not sure if my interpretation of your question is correct, apologies if not. From what I gather you are using PCA as an initial tool to show you what variables are the most important in explaining the dataset. You then want to go back to your original data, select these variables quickly without manual coding each time, and use them for some other analysis.
If this is correct then I have saved the data from the contribution plot, filtered out the variables that have the greatest contribution, and used that result to create a new data frame with these variables alone.
Based on your comment, where you said you wanted to 'Find variables with value greater than 5 in Dim.1 AND Dim.2 and save these variables to a new data frame', I would do this:
(This keeps all the original variables in our new data frame since they all contributed more than 5% to the total variance)