CINXE.COM
R Principal Component Analysis: Apply and Understand R PCA in Minutes
<!DOCTYPE html><!-- Last Published: Fri Mar 28 2025 14:11:01 GMT+0000 (Coordinated Universal Time) --><html data-wf-domain="www.appsilon.com" data-wf-page="65fad590f3d052ee3690071d" data-wf-site="6525256482c9e9a06c7a9d3c" lang="en" data-wf-locale="en" data-wf-collection="65fad590f3d052ee36900543" data-wf-item-slug="r-principal-component-analysis"><head><meta charset="utf-8"/><title>R Principal Component Analysis: Apply and Understand R PCA in Minutes</title><meta content="Struggling to understand Principal Component Analysis (PCA)? This guide will demystify the concepts and demonstrate practical implementation in R programming language." name="description"/><meta content="R Principal Component Analysis: Apply and Understand R PCA in Minutes" property="og:title"/><meta content="Struggling to understand Principal Component Analysis (PCA)? This guide will demystify the concepts and demonstrate practical implementation in R programming language." property="og:description"/><meta content="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r.png" property="og:image"/><meta content="R Principal Component Analysis: Apply and Understand R PCA in Minutes" property="twitter:title"/><meta content="Struggling to understand Principal Component Analysis (PCA)? This guide will demystify the concepts and demonstrate practical implementation in R programming language." property="twitter:description"/><meta content="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r.png" property="twitter:image"/><meta property="og:type" content="website"/><meta content="summary_large_image" name="twitter:card"/><meta content="width=device-width, initial-scale=1" name="viewport"/><link href="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/css/appsilon-staging.webflow.3bc3d5633.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com" rel="preconnect"/><link href="https://fonts.gstatic.com" rel="preconnect" crossorigin="anonymous"/><script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js" type="text/javascript"></script><script type="text/javascript">WebFont.load({ google: { families: ["Maven Pro:regular,500,600,700,800","Titillium Web:regular,600,700","Caladea:regular,italic,700,700italic:latin,latin-ext"] }});</script><script type="text/javascript">!function(o,c){var n=c.documentElement,t=" w-mod-";n.className+=t+"js",("ontouchstart"in o||o.DocumentTouch&&c instanceof DocumentTouch)&&(n.className+=t+"touch")}(window,document);</script><link href="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/6539712fd404135782293921_Fav_Appsi.png" rel="shortcut icon" type="image/x-icon"/><link href="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/6539716202ecf45338574631_fav_big_appsi.png" rel="apple-touch-icon"/><link href="https://www.appsilon.com/post/r-principal-component-analysis" rel="canonical"/><link href="rss.xml" rel="alternate" title="RSS Feed" type="application/rss+xml"/><!-- Basin --> <script src="https://js.usebasin.com/v2.3.0.min.js" async></script> <script src="https://www.google.com/recaptcha/api.js?render=6Les66kUAAAAANyLrgkl7iuN4JUpNlB5upaMovI4"></script> <!-- Start cookieyes banner --> <script id="cookieyes" type="text/javascript" src="https://cdn-cookieyes.com/client_data/b2b62ebd31e49a40253ec9d4/script.js"></script> <!-- End cookieyes banner --> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5F7GGSBS');</script> <!-- End Google Tag Manager --> <!-- Please keep this css code to improve the font quality--> <style> * { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -o-font-smoothing: antialiased; } </style> <!-- [Attributes by Finsweet] Code Highlight --> <script async src="https://cdn.jsdelivr.net/npm/@finsweet/attributes-codehighlight@1/codehighlight.js"></script> <!-- [Attributes by Finsweet] Powerful Rich Text --> <script defer src="https://cdn.jsdelivr.net/npm/@finsweet/attributes-richtext@1/richtext.js"></script> <!-- [Attributes by Finsweet] Read Time --> <script defer src="https://cdn.jsdelivr.net/npm/@finsweet/attributes-readtime@1/readtime.js"></script> <script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c%2F652d31f3dc22d7b4ee708e44%2F65ec985647ad1cc6043b7e3a%2Fclarity_script-3.8.0.js" type="text/javascript"></script><script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c%2F66ba5a08efe71070f98dd10a%2F67613cc1dea3f27301ef65f3%2F7p55wesl38-1.1.1.js" type="text/javascript"></script></head><body><div class="set-all-components-to-display-none-and-use-this-div-to-create-a-symbol"></div><div class="global-styles w-embed w-iframe"><!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5F7GGSBS" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <style> html { font-size: 1.125rem; } @media screen and (max-width:1920px) { html { font-size: calc(0.625rem + 0.41666666666666674vw); } } @media screen and (max-width:1440px) { html { font-size: calc(0.8126951092611863rem + 0.20811654526534862vw); } } @media screen and (max-width:479px) { html { font-size: calc(0.7494769874476988rem + 0.8368200836820083vw); } } /* Focus state style for keyboard navigation for the focusable elements */ *[tabindex]:focus-visible, input[type="file"]:focus-visible { outline: 0.125rem solid #4d65ff; outline-offset: 0.125rem; } /* Get rid of top margin on first element in any rich text element */ .w-richtext > :not(div):first-child, .w-richtext > div:first-child > :first-child { margin-top: 0 !important; } /* Get rid of bottom margin on last element in any rich text element */ .w-richtext>:last-child, .w-richtext ol li:last-child, .w-richtext ul li:last-child { margin-bottom: 0 !important; } /* Prevent all click and hover interaction with an element */ .pointer-events-off { pointer-events: none; } /* Enables all click and hover interaction with an element */ .pointer-events-on { pointer-events: auto; } /* Create a class of .div-square which maintains a 1:1 dimension of a div */ .div-square::after { content: ""; display: block; padding-bottom: 100%; } /* Make sure containers never lose their center alignment */ .container-medium,.container-small, .container-large { margin-right: auto !important; margin-left: auto !important; } /* Make the following elements inherit typography styles from the parent and not have hardcoded values. Important: You will not be able to style for example "All Links" in Designer with this CSS applied. Uncomment this CSS to use it in the project. Leave this message for future hand-off. */ /* a, .w-input, .w-select, .w-tab-link, .w-nav-link, .w-dropdown-btn, .w-dropdown-toggle, .w-dropdown-link { color: inherit; text-decoration: inherit; font-size: inherit; } */ /* Apply "..." after 3 lines of text */ .text-style-3lines { display: -webkit-box; overflow: hidden; -webkit-line-clamp: 3; -webkit-box-orient: vertical; } /* Apply "..." after 2 lines of text */ .text-style-2lines { display: -webkit-box; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } /* Adds inline flex display */ .display-inlineflex { display: inline-flex; } /* These classes are never overwritten */ .hide { display: none !important; } @media screen and (max-width: 991px) { .hide, .hide-tablet { display: none !important; } } @media screen and (max-width: 767px) { .hide-mobile-landscape{ display: none !important; } } @media screen and (max-width: 479px) { .hide-mobile{ display: none !important; } } .margin-0 { margin: 0rem !important; } .padding-0 { padding: 0rem !important; } .spacing-clean { padding: 0rem !important; margin: 0rem !important; } .margin-top { margin-right: 0rem !important; margin-bottom: 0rem !important; margin-left: 0rem !important; } .padding-top { padding-right: 0rem !important; padding-bottom: 0rem !important; padding-left: 0rem !important; } .margin-right { margin-top: 0rem !important; margin-bottom: 0rem !important; margin-left: 0rem !important; } .padding-right { padding-top: 0rem !important; padding-bottom: 0rem !important; padding-left: 0rem !important; } .margin-bottom { margin-top: 0rem !important; margin-right: 0rem !important; margin-left: 0rem !important; } .padding-bottom { padding-top: 0rem !important; padding-right: 0rem !important; padding-left: 0rem !important; } .margin-left { margin-top: 0rem !important; margin-right: 0rem !important; margin-bottom: 0rem !important; } .padding-left { padding-top: 0rem !important; padding-right: 0rem !important; padding-bottom: 0rem !important; } .margin-horizontal { margin-top: 0rem !important; margin-bottom: 0rem !important; } .padding-horizontal { padding-top: 0rem !important; padding-bottom: 0rem !important; } .margin-vertical { margin-right: 0rem !important; margin-left: 0rem !important; } .padding-vertical { padding-right: 0rem !important; padding-left: 0rem !important; } /* Apply "..." at 100% width */ .truncate-width { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Removes native scrollbar */ .no-scrollbar { -ms-overflow-style: none; overflow: -moz-scrollbars-none; } .no-scrollbar::-webkit-scrollbar { display: none; } </style></div><div data-animation="default" data-collapse="medium" data-duration="100" data-easing="ease" data-easing2="ease" role="banner" class="menu_navbar w-nav"><nav class="menu_wrapper"><aside class="menu_top-bar"><div class="is-bg-blue stripe"><div class="padding-global"><div class="is-pad-tb-8"><div class="text-top-stripe"><div class="text-block-11"><strong>ShinyConf 2025 registration is now open!</strong> Be part of the largest virtual Shiny conference. <a href="https://events.ringcentral.com/events/shinyconf-2025" target="_blank"><span class="is-span-blue"><strong>Register Now</strong></span></a></div></div></div></div></div></aside><nav class="menu_bottom_bar"><div class="padding-global"><div class="navbar5_container"><a href="/" class="navbar5_logo-link w-nav-brand"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/6539655f4ca172cfc5deaad8_Appsilon_logo.svg" loading="lazy" alt="" class="navbar5_logo"/></a><nav role="navigation" class="navbar5_menu w-nav-menu"><div class="navbar5_menu-left"><div data-hover="false" data-delay="300" data-w-id="585cd299-050b-0a77-9657-a1c9e907eeac" class="navbar5_menu-dropdown w-dropdown"><div class="navbar5_dropdown-toggle w-dropdown-toggle"><div>Services</div><div class="label-new main-menu"></div><div class="dropdown-chevron w-embed"><svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5.00016 5.90982C4.81016 5.90982 4.62016 5.83982 4.47016 5.68982L0.940156 2.15982C0.650156 1.86982 0.650156 1.38982 0.940156 1.09982C1.23016 0.809824 1.71016 0.809824 2.00016 1.09982L5.00016 4.09982L8.00016 1.09982C8.29016 0.809824 8.77016 0.809824 9.06016 1.09982C9.35016 1.38982 9.35016 1.86982 9.06016 2.15982L5.53016 5.68982C5.38016 5.83982 5.19016 5.90982 5.00016 5.90982Z" fill="#10212E"/> </svg></div></div><nav class="navbar5_dropdown-list w-dropdown-list"><div class="navbar5_container"><div class="navbar5_dropdown-content"><div class="navbar5_dropdown-content-left"><div class="navbar5_dropdown-link-list"><div class="spacer-xxsmall"></div><a href="/services/data-dashboards" class="navbar5_dropdown-link w-inline-block"><div class="navbar5_icon-wrapper"><div class="icon-embed-xsmall-10 w-embed"><svg width="168" height="168" viewBox="0 0 168 168" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M154 154.001H14C11.13 154.001 8.75 151.621 8.75 148.751C8.75 145.881 11.13 143.501 14 143.501H154C156.87 143.501 159.25 145.881 159.25 148.751C159.25 151.621 156.87 154.001 154 154.001Z" fill="#0099F9"/> <path d="M68.2539 27.999V153.999H99.7539V27.999C99.7539 20.299 96.6039 13.999 87.1539 13.999H80.8539C71.4039 13.999 68.2539 20.299 68.2539 27.999Z" fill="#0099F9"/> <path opacity="0.4" d="M20.9951 69.999V153.999H48.9951V69.999C48.9951 62.299 46.1951 55.999 37.7951 55.999H32.1951C23.7951 55.999 20.9951 62.299 20.9951 69.999Z" fill="#0099F9"/> <path opacity="0.4" d="M118.994 105V154H146.994V105C146.994 97.2998 144.194 90.9998 135.794 90.9998H130.194C121.794 90.9998 118.994 97.2998 118.994 105Z" fill="#0099F9"/> </svg></div></div><div class="navbar5_item-right"><div class="text-size-regular text-weight-semibold">Dashboards in Shiny for R and Python</div></div></a><a href="/services/platform" class="navbar5_dropdown-link w-inline-block"><div class="navbar5_icon-wrapper"><div class="icon-embed-xsmall-10 w-embed"><svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.4" d="M13.332 65.0009C10.5987 65.0009 8.33203 62.7342 8.33203 60.0009V43.3342C8.33203 24.0009 24.0654 8.33423 43.332 8.33423H59.9987C62.732 8.33423 64.9987 10.6009 64.9987 13.3342C64.9987 16.0676 62.732 18.3342 59.9987 18.3342H43.332C29.532 18.3342 18.332 29.5342 18.332 43.3342V60.0009C18.332 62.7342 16.0654 65.0009 13.332 65.0009Z" fill="#0099F9"/> <path d="M146.667 65.0009C143.933 65.0009 141.667 62.7342 141.667 60.0009V43.3342C141.667 29.5342 130.467 18.3342 116.667 18.3342H100C97.2667 18.3342 95 16.0676 95 13.3342C95 10.6009 97.2667 8.33423 100 8.33423H116.667C135.933 8.33423 151.667 24.0009 151.667 43.3342V60.0009C151.667 62.7342 149.4 65.0009 146.667 65.0009Z" fill="#0099F9"/> <path opacity="0.4" d="M116.667 151.667H106.667C103.934 151.667 101.667 149.401 101.667 146.667C101.667 143.934 103.934 141.667 106.667 141.667H116.667C130.467 141.667 141.667 130.467 141.667 116.667V106.667C141.667 103.934 143.934 101.667 146.667 101.667C149.4 101.667 151.667 103.934 151.667 106.667V116.667C151.667 136.001 135.934 151.667 116.667 151.667Z" fill="#0099F9"/> <path d="M59.9987 151.667H43.332C24.0654 151.667 8.33203 136 8.33203 116.667V100C8.33203 97.2667 10.5987 95 13.332 95C16.0654 95 18.332 97.2667 18.332 100V116.667C18.332 130.467 29.532 141.667 43.332 141.667H59.9987C62.732 141.667 64.9987 143.933 64.9987 146.667C64.9987 149.4 62.732 151.667 59.9987 151.667Z" fill="#0099F9"/> <path d="M60.002 34.9998H46.6686C39.0686 34.9998 35.002 38.9998 35.002 46.6664V59.9998C35.002 67.6664 39.0686 71.6664 46.6686 71.6664H60.002C67.602 71.6664 71.6686 67.6664 71.6686 59.9998V46.6664C71.6686 38.9998 67.602 34.9998 60.002 34.9998Z" fill="#0099F9"/> <path opacity="0.4" d="M113.333 34.9998H99.9997C92.3997 34.9998 88.333 38.9998 88.333 46.6664V59.9998C88.333 67.6664 92.3997 71.6664 99.9997 71.6664H113.333C120.933 71.6664 125 67.6664 125 59.9998V46.6664C125 38.9998 120.933 34.9998 113.333 34.9998Z" fill="#0099F9"/> <path opacity="0.4" d="M60.002 88.3326H46.6686C39.0686 88.3326 35.002 92.3326 35.002 99.9993V113.333C35.002 120.999 39.0686 124.999 46.6686 124.999H60.002C67.602 124.999 71.6686 120.999 71.6686 113.333V99.9993C71.6686 92.3326 67.602 88.3326 60.002 88.3326Z" fill="#0099F9"/> <path d="M113.333 88.3326H99.9997C92.3997 88.3326 88.333 92.3326 88.333 99.9993V113.333C88.333 120.999 92.3997 124.999 99.9997 124.999H113.333C120.933 124.999 125 120.999 125 113.333V99.9993C125 92.3326 120.933 88.3326 113.333 88.3326Z" fill="#0099F9"/> </svg></div></div><div class="navbar5_item-right"><div class="text-size-regular text-weight-semibold">Cloud Infrastructure & Computing Environments</div></div></a><a href="/services/sce" class="navbar5_dropdown-link w-inline-block"><div class="navbar5_icon-wrapper"><div class="icon-embed-xsmall-10 w-embed"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.4" d="M5.32914 19.42C5.21914 19.42 5.09914 19.39 4.99914 19.34L2.77914 18.23C2.52914 18.1 2.36914 17.84 2.36914 17.56V14.78C2.36914 14.37 2.70914 14.03 3.11914 14.03C3.52914 14.03 3.86914 14.37 3.86914 14.78V17.09L5.67914 17.99C6.04914 18.18 6.19913 18.63 6.01913 19C5.86913 19.26 5.60914 19.42 5.32914 19.42Z" fill="#0099F9"/> <path d="M11.9995 22.75C11.9395 22.75 11.8795 22.74 11.8295 22.73C11.7695 22.72 11.7095 22.69 11.6495 22.66L9.43948 21.56C9.06948 21.37 8.91947 20.92 9.09947 20.55C9.28947 20.18 9.73947 20.03 10.1095 20.21L11.2495 20.78V19.22C11.2495 18.81 11.5895 18.47 11.9995 18.47C12.4095 18.47 12.7495 18.81 12.7495 19.22V20.78L13.8895 20.21C14.2595 20.03 14.7095 20.18 14.8995 20.55C15.0895 20.92 14.9395 21.37 14.5595 21.56L12.3495 22.66C12.2895 22.69 12.2295 22.71 12.1695 22.73C12.1095 22.74 12.0595 22.75 11.9995 22.75Z" fill="#0099F9"/> <path opacity="0.4" d="M18.6702 19.42C18.4002 19.42 18.1302 19.27 18.0002 19.01C17.8102 18.64 17.9602 18.19 18.3402 18L20.1502 17.1001V14.79C20.1502 14.38 20.4902 14.04 20.9002 14.04C21.3102 14.04 21.6502 14.38 21.6502 14.79V17.5701C21.6502 17.8501 21.4902 18.1101 21.2402 18.2401L19.0202 19.3501C18.8902 19.3901 18.7802 19.42 18.6702 19.42Z" fill="#0099F9"/> <path d="M11.9995 14.42C11.5895 14.42 11.2495 14.08 11.2495 13.67V11.36L9.43948 10.4601C9.06948 10.2701 8.91947 9.82004 9.09947 9.45004C9.28947 9.08004 9.73947 8.93005 10.1095 9.11005L11.9995 10.05L13.8895 9.11005C14.2595 8.93005 14.7095 9.07004 14.8995 9.45004C15.0895 9.82004 14.9395 10.2701 14.5595 10.4601L12.7495 11.36V13.67C12.7495 14.08 12.4095 14.42 11.9995 14.42Z" fill="#0099F9"/> <path opacity="0.4" d="M3.10938 9.96988C2.69938 9.96988 2.35938 9.62988 2.35938 9.21988V6.45988V6.44987C2.35938 6.38987 2.36937 6.32987 2.37937 6.27987C2.39937 6.19987 2.42938 6.12987 2.46938 6.05987C2.49938 6.00987 2.52937 5.96987 2.56937 5.92987C2.60937 5.88987 2.65937 5.84988 2.70937 5.81988C2.72937 5.80988 2.75937 5.78987 2.77937 5.77987L4.98937 4.67987C5.35937 4.49987 5.80937 4.63988 5.99937 5.01988C6.18937 5.38988 6.03938 5.83987 5.65938 6.02987L4.77937 6.46988L5.65938 6.90988C6.02938 7.09988 6.17937 7.54987 5.99937 7.91987C5.81937 8.28987 5.35937 8.43987 4.98937 8.25987L3.84937 7.68988V9.24987C3.85937 9.63987 3.52937 9.96988 3.10938 9.96988Z" fill="#0099F9"/> <path d="M14.2198 3.86004C14.1098 3.86004 13.9898 3.83004 13.8898 3.78004L11.9998 2.84004L10.1098 3.78004C9.73979 3.97004 9.28979 3.82004 9.09979 3.44004C8.90979 3.07004 9.05979 2.62003 9.43979 2.43003L11.6598 1.32005C11.8698 1.21005 12.1198 1.21005 12.3298 1.32005L14.5498 2.43003C14.9198 2.62003 15.0698 3.07004 14.8898 3.44004C14.7598 3.71004 14.4998 3.86004 14.2198 3.86004Z" fill="#0099F9"/> <path opacity="0.4" d="M20.8904 9.97002C20.4804 9.97002 20.1404 9.63001 20.1404 9.22002V7.66002L19.0004 8.23001C18.6304 8.42001 18.1804 8.27001 17.9904 7.89001C17.8004 7.52001 17.9504 7.07002 18.3304 6.88002L19.2104 6.44002L18.3304 6.00001C17.9604 5.81001 17.8104 5.36002 17.9904 4.99002C18.1704 4.62002 18.6304 4.47001 19.0004 4.65001L21.2104 5.75001C21.2304 5.76001 21.2604 5.77001 21.2804 5.79001C21.3404 5.82001 21.3904 5.87001 21.4404 5.92001C21.4704 5.96001 21.5004 6.00001 21.5304 6.04001C21.5704 6.11001 21.6004 6.18001 21.6204 6.26001C21.6304 6.32001 21.6404 6.38001 21.6404 6.43001V6.44002V9.20001C21.6404 9.64001 21.3004 9.97002 20.8904 9.97002Z" fill="#0099F9"/> </svg></div></div><div class="navbar5_item-right"><div class="text-size-regular text-weight-semibold">Statistical Computing Environments</div></div></a></div><div class="navbar5_dropdown-link-list"><div class="spacer-xxsmall"></div><a href="/services/gxp-regulatory-compliance" class="navbar5_dropdown-link w-inline-block"><div class="navbar5_icon-wrapper"><div class="icon-embed-xsmall-10 w-embed"><svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.4" d="M113.52 0H46.48C17.36 0 0 17.36 0 46.48V113.52C0 142.64 17.36 160 46.48 160H113.52C142.64 160 160 142.64 160 113.52V46.48C160 17.36 142.64 0 113.52 0Z" fill="#0099F9"/> <path d="M130.48 54.96C130.48 58.24 127.84 60.96 124.48 60.96H82.4805C79.2005 60.96 76.4805 58.24 76.4805 54.96C76.4805 51.68 79.2005 48.96 82.4805 48.96H124.48C127.84 48.96 130.48 51.68 130.48 54.96Z" fill="#0099F9"/> <path d="M63.7605 47.2L45.7605 65.2C44.5605 66.4 43.0405 66.96 41.5205 66.96C40.0005 66.96 38.4005 66.4 37.2805 65.2L31.2805 59.2C28.8805 56.88 28.8805 53.04 31.2805 50.72C33.6005 48.4 37.3605 48.4 39.7605 50.72L41.5205 52.48L55.2805 38.72C57.6005 36.4 61.3605 36.4 63.7605 38.72C66.0805 41.04 66.0805 44.88 63.7605 47.2Z" fill="#0099F9"/> <path d="M130.48 110.96C130.48 114.24 127.84 116.96 124.48 116.96H82.4805C79.2005 116.96 76.4805 114.24 76.4805 110.96C76.4805 107.68 79.2005 104.96 82.4805 104.96H124.48C127.84 104.96 130.48 107.68 130.48 110.96Z" fill="#0099F9"/> <path d="M63.7605 103.2L45.7605 121.2C44.5605 122.4 43.0405 122.96 41.5205 122.96C40.0005 122.96 38.4005 122.4 37.2805 121.2L31.2805 115.2C28.8805 112.88 28.8805 109.04 31.2805 106.72C33.6005 104.4 37.3605 104.4 39.7605 106.72L41.5205 108.48L55.2805 94.72C57.6005 92.4 61.3605 92.4 63.7605 94.72C66.0805 97.04 66.0805 100.88 63.7605 103.2Z" fill="#0099F9"/> </svg></div></div><div class="navbar5_item-right"><div class="text-size-regular text-weight-semibold">GxP Compliance in R & Computing Environments</div></div></a><a href="/services/gxp-audit" class="navbar5_dropdown-link w-inline-block"><div class="navbar5_icon-wrapper"><div class="icon-embed-xsmall-10 w-embed"><svg width="auto" height="auto" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.4" d="M16.2391 3.6499H7.75906C5.28906 3.6499 3.28906 5.6599 3.28906 8.1199V17.5299C3.28906 19.9899 5.29906 21.9999 7.75906 21.9999H16.2291C18.6991 21.9999 20.6991 19.9899 20.6991 17.5299V8.1199C20.7091 5.6499 18.6991 3.6499 16.2391 3.6499Z" fill="#6CA5E2"/> <path d="M14.3498 2H9.64977C8.60977 2 7.75977 2.84 7.75977 3.88V4.82C7.75977 5.86 8.59977 6.7 9.63977 6.7H14.3498C15.3898 6.7 16.2298 5.86 16.2298 4.82V3.88C16.2398 2.84 15.3898 2 14.3498 2Z" fill="#6CA5E2"/> <path d="M10.81 16.9501C10.62 16.9501 10.43 16.8801 10.28 16.7301L8.78 15.2301C8.49 14.9401 8.49 14.4601 8.78 14.1701C9.07 13.8801 9.55 13.8801 9.84 14.1701L10.81 15.1401L14.28 11.6701C14.57 11.3801 15.05 11.3801 15.34 11.6701C15.63 11.9601 15.63 12.4401 15.34 12.7301L11.34 16.7301C11.2 16.8801 11 16.9501 10.81 16.9501Z" fill="#6CA5E2"/> </svg></div></div><div class="navbar5_item-right"><div class="text-size-regular text-weight-semibold">GxP Compliance Audit</div></div><div class="label-new"></div></a></div></div><div class="navbar5_dropdown-content-right"><div class="navbar5_dropdown-content-wrapper z-index-1"><div class="is-txt-label small">New Case Study</div><div id="w-node-_585cd299-050b-0a77-9657-a1c9e907eef1-bb4be1c0" class="navbar5_blog-list-wrapper"><div class="navbar5_blog-list"><div class="w-dyn-list"><div role="list" class="w-dyn-items"><div role="listitem" class="w-dyn-item"><a href="https://www.appsilon.com/case-studies/accelerating-clinical-trials-teal" class="navbar5_blog-item w-inline-block"><div class="navbar5_blog-image-wrapper"><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67e687d050366c71eb7314af_teal-cs.webp" loading="lazy" alt="" sizes="100vw" srcset="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67e687d050366c71eb7314af_teal-cs-p-500.webp 500w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67e687d050366c71eb7314af_teal-cs-p-800.webp 800w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67e687d050366c71eb7314af_teal-cs.webp 1000w" class="navbar5_blog-image"/></div><div class="navbar5_large-item-content"><div class="text-weight-semibold text-style-2lines">Accelerating Clinical Trials with {teal}: Data Exploratory Apps Built in Weeks, Not Months</div><div class="spacer-tiny-4"></div><p class="text-size-small text-style-2lines">Learn how Appsilon R developers contribute to {teal}, an open-source Shiny framework for faster and more interactive clinical data exploration.</p><div class="spacer-xsmall"></div><div class="label_read-more-arrow left"><div class="text-size-tiny text-weight-semibold">Read More</div><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/6637c4880685ccf8c40766cd_Arrow_Right.svg" loading="lazy" alt=""/></div></div></a></div></div></div></div></div></div><div class="navbar5_dropdown-background-layer"></div></div></div></div></nav></div><a href="/case-studies/collection" class="navbar5_link w-nav-link">Case Studies</a><link rel="prefetch" href="/case-studies/collection"/><a href="/data-for-good" class="navbar5_link w-nav-link">Data4Good</a><a href="/careers" class="navbar5_link w-nav-link">Careers</a><a href="/resources/collection" class="navbar5_link w-nav-link">Resources</a><a href="/blog" class="navbar5_link w-nav-link">Blog</a></div><div class="navbar5_menu-right"><a href="/contact-us" class="button menu w-button">Talk to our Experts</a><link rel="prerender" href="/contact-us"/></div></nav><div class="navbar5_menu-button w-nav-button"><div class="menu-icon"><div class="menu-icon_line-top"></div><div class="menu-icon_line-middle"><div class="menu-icon_line-middle-inner"></div></div><div class="menu-icon_line-bottom"></div></div></div></div></div></nav></nav></div><div class="page_warp blogpost"><main class="main-wrapper"><article class="section_blog-post4-content"><div class="padding-global-19"><div class="container-large-9"><div class="padding-bottom padding-xhuge"><div class="blog-post4-content_component"><div class="blogpost_wrapper"><div class="blog-post4-content_content"><div class="blog-post4-header_title-wrapper"><h1>R Principal Component Analysis: Apply and Understand R PCA in Minutes</h1><div class="spacer-xsmall"></div><div class="time_wrapper"><div class="text-size-small text-color-grey">Reading time:</div><div class="div-block-21"><div fs-readtime-element="time" class="text-size-small text-color-grey text-weight-semibold">time</div><div class="text-size-small text-color-grey">min</div></div><div class="div-block-53"></div><div class="collection-list-wrapper-3 w-dyn-list"><div role="list" class="collection-list-10 w-dyn-items"><div role="listitem" class="w-dyn-item"><a href="/blog-tags/r" class="link-block-24 w-inline-block"><div class="blog-item-tag blogpost">r</div></a></div><div role="listitem" class="w-dyn-item"><a href="/blog-tags/data-visualization" class="link-block-24 w-inline-block"><div class="blog-item-tag blogpost">data visualization</div></a></div><div role="listitem" class="w-dyn-item"><a href="/blog-tags/ai-research" class="link-block-24 w-inline-block"><div class="blog-item-tag blogpost">ai&research</div></a></div></div></div></div><div class="spacer-small"></div><div class="div-block-15"><a href="/author/dario" class="link-block-23 w-inline-block"><div class="author_wrapper"><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/65b2843aa5b4818ebf9ef86c_Dario.webp" loading="lazy" alt="" class="blogpost_author_image shadow-medium"/><div class="div-block-19"><div class="div-block-22"><div>By:</div><div class="text-weight-bold">Dario Radečić</div></div></div></div></a><div class="text-size-small text-color-grey">November 7, 2024</div></div><div class="spacer-small"></div></div><img alt="" loading="eager" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r.png" sizes="100vw" srcset="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r-p-500.png 500w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r-p-800.png 800w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r-p-1080.png 1080w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r-p-1600.png 1600w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c81010f8414b9d7636cd6_r.png 1921w" class="blog-post4-header_image"/><div class="bodypost-wrapper"><div fs-readtime-element="contents" fs-codehighlight-element="code" fs-codehighlight-theme="googlecode" fs-toc-element="contents" fs-toc-offsettop="8rem" fs-richtext-element="rich-text" class="bodypost-rich-text w-richtext"><p>Did you ever have to deal with a highly-dimensional dataset? Think hundreds of columns. If so, were all the features (dimensions) relevant for analysis and modeling? Of course, they weren’t, that’s rarely the case.</p><p><strong>The good news:</strong> Data Science has a set of algorithms that enable you to see what matters and what doesn’t. One such tool is Principal Component Analysis (PCA). It’s an unsupervised algorithm used to reduce dimensionality by calculating <em>principal components</em> - new features that capture the essence of your data, hopefully in fewer dimensions.</p><p>This article will teach you the basics of Principal Component Analysis in R focusing on application, drawing insights, and visualization. We’ll use the well-known Iris dataset for simplicity, but the methods described are applicable to any tabular dataset out there.</p><p>Let’s dig in!</p><blockquote><em>Coding a classification machine learning algorithm? </em><a href="https://www.appsilon.com/post/machine-learning-evaluation-metrics-classification"><em>Use these 10 metrics to evaluate the performance of your model</em></a><em>.</em></blockquote><h3>Table of Contents:</h3><ul role="list"><li>Introduction to Principal Component Analysis</li><li>Principal Component Analysis in R Prerequisites - Get Your Data in Order</li><li>R PCA in Action</li><li>Visualizing Principal Component Analysis in R</li><li>Summing up R PCA</li></ul><h2>Introduction to Principal Component Analysis</h2><p>PCA is a mathematical technique used for dimensionality reduction. The ultimate goal is to <strong>reduce the number of features</strong> your dataset has while preserving most of the original information. </p><p>After applying PCA to your dataset, you’ll end up with seemingly uninterpretable principal components instead of your original features. Each of these components captures <strong>one-directional variance of the entire dataset</strong>. </p><p>This comes in handy because you can typically use 2-3 components to capture some decent percentage of variance in the original dataset, and then <strong>visualize</strong> them to see how the data is spread out. Of course, you won’t get a full picture since you need N principal components to perfectly describe N dataset features. Still, you’ll gain a visual understanding of your data that’s impossible to get from the raw features.</p><p>The entire algorithm can be boiled down to a three-step process:</p><ol role="list"><li><strong>Data Scaling</strong> - Essentially, you don’t want some features to be voted as “more relevant” due to scale differences. In other words, 1 meter is the same as 1000 millimeters, but machine learning algorithms tend to favor features with greater magnitude. You want all your features centered around 0 with a standard deviation of 1.</li><li><strong>Covariance Matrix Calculation</strong> - The measure of variance reports variation of a single random variable. Covariance does the same thing but for two random variables. The covariance matrix will be a symmetrical square matrix with variances on the diagonal and covariances on other elements.</li><li><strong>Eigendecomposition</strong> - This long word from linear algebra represents the process of decomposing a square matrix into eigenvectors (unit vectors) and eigenvalues (magnitudes of unit vectors). Calculating these basically computes principal components. Eigenvectors of symmetrical matrices are orthogonal, meaning the first principal component will explain most of the dataset’s variance, the second will explain most of the remaining variance in the orthogonal direction, and so on.</li></ol><p>The resulting principal components will be sorted by <strong>percentage of explained variance</strong>. From there on, you’re the boss! You decide how many components should you keep. For example, if you’re starting out with 100 features, but the first 3 principal components explain 95% of the variance, it makes sense to keep only these three for visualization and model training. You’ll end up with a much simpler model as a result.</p><p>Luckily for you, we won’t implement the PCA algorithm from scratch. It makes no sense to do so since R comes with a convenient `prcomp()` function that does the job. Before exploring it, let’s make sure our data is adequate.</p><h2>Principal Component Analysis in R Prerequisites - Get Your Data in Order</h2><p>As mentioned earlier, we’ll use the Iris dataset for the sake of simplicity. All principles will work the same on larger, real-world datasets.</p><p>The following snippet shows all the R packages needed to follow along. If you don’t have any of these installed, run the `install.packages(“<package-name>”)` command from the R console. The snippet also loads the Iris dataset and prints the first couple of records:</p><div class="w-embed"><pre><code class="language-r">library(dplyr) library(plotly) library(reshape2) library(ggplot2) library(gridExtra) library(factoextra) data <- iris head(data)</code></pre></div><figure style="max-width:1302pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187b0_66a0f1f59f0d79ae359cfea0_1.webp" loading="lazy" alt=""/></div><figcaption>Image 1 - Head of the Iris dataset</figcaption></figure><h3>Missing Values</h3><p>The first order of business is dealing with missing values. The Iris dataset doesn’t contain any, but for the sake of argument let’s say we don’t know that.</p><p>The following code snippet will print <strong>missing value column sums</strong> - the number of missing values present in the dataset per column:</p><div class="w-embed"><pre><code class="language-r">colSums(is.na(data))</code></pre></div><figure style="max-width:1418pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187a0_66a0f216cc9b6a3e3486a42f_2.webp" loading="lazy" alt=""/></div><figcaption>Image 2 - Missing value count per column</figcaption></figure><p>If your dataset contains some, you should either impute or remove them before proceeding.</p><blockquote><em>New to missing values in machine learning? </em><a href="https://www.appsilon.com/post/imputation-in-r"><em>Read our guide to learn the top 3 ways to impute missing values in R</em></a><em>.</em></blockquote><h3>Removing the Target Variable</h3><p>Principal Component Analysis obviously works only on numerical data. Our dataset has a `Species` column that is textual and represents the target variable. We’ll create two new variables - `X` and `y`. The prior represents the numerical features while the latter holds the target variable values:</p><div class="w-embed"><pre><code class="language-r">X <- data %>% select(-Species) y <- data %>% select(Species)</code></pre></div><h3>Data Standardization</h3><p>As mentioned in the theoretical section, all of your features should be on an identical scale. You’ll want to use <em>Z-scaling</em>, also known as <em>Standard scaling</em>, implemented in R’s `scale()` function. </p><p>This will compute <strong>Z-scores</strong> - values that are the result of subtracting the average value from individual values in the column, and then dividing it by the standard deviation of the column:</p><div class="w-embed"><pre><code class="language-r">X_scaled <- scale(X) head(X_scaled)</code></pre></div><figure style="max-width:1200pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187ad_66a0f24ade524dc2abadc690_3.webp" loading="lazy" alt=""/></div><figcaption>Image 3 - Standardized feature values</figcaption></figure><p>In case you have a dataset where a column has a constant value, its standard deviation will be 0. Since <strong>division with 0 is not possible</strong>, you’ll want to exclude columns as these from data scaling, and then glue them back in the correct order.</p><p>Anyhow, you can test if data scaling was successful by calculating the average mean and average standard deviation of all columns:</p><div class="w-embed"><pre><code class="language-r"># Default mean and standard deviation default_mu <- paste("Default mu:", mean(colMeans(X))) default_sd <- paste("Default sd:", mean(apply(X, 2, sd))) # Standardized mean and standard deviation standardized_mu <- paste("Standardized mu:", mean(colMeans(X_scaled))) standardized_sd <- paste("Standardized sd:", mean(apply(X_scaled, 2, sd))) print(default_mu) print(default_sd) print(standardized_mu) print(standardized_sd)</code></pre></div><figure style="max-width:1008pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc1879c_66a0f26b0fc9fa9fae540931_4.webp" loading="lazy" alt=""/></div><figcaption>Image 4 - Descriptive statistics comparison</figcaption></figure><p>Every column now has an average value of 0 with a standard deviation of 1 - just the format you need to calculate principal components.</p><h2>R PCA in Action</h2><p>PCA in R boils down to calling the `prcomp()` function and passing in a dataframe of scaled numerical features:</p><div class="w-embed"><pre><code class="language-r">pca_result <- prcomp(X_scaled) summary(pca_result)</code></pre></div><figure style="max-width:1140pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc18798_66a0f284d2238ff45cd3d070_5.webp" loading="lazy" alt=""/></div><figcaption>Image 5 - R PCA summary results</figcaption></figure><p>What you should be looking at is the <strong>proportion of variance</strong> and <strong>cumulative proportion</strong> values. The prior tells you how much variance each principal component captures from the entire dataset, while the latter shows how many components you need to capture some percentage of total variance. For example, if you decide 95% of the variance is enough, the first two principal components are all you need.</p><p>For the sake of easier analysis and visualization later on, we’ll create a helper dataframe that basically rearranges the values of `summary(pca_result)`: </p><figure style="max-width:1258pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc18791_66a0f2a46ac947fc8e24f43d_6.webp" loading="lazy" alt=""/></div><figcaption>Image 6 - R PCA summary results (2)</figcaption></figure><p>Now let’s dive into the interesting stuff - visualization.</p><h2>Visualizing Principal Component Analysis in R</h2><p>The original Iris dataset is difficult to visualize in its entirety. There are 4 numerical features and one target variable. We humans still haven’t figured out a way to see past the third dimension. Principal components can help since you’re visualizing the information from the original data but in a space humans can interpret.</p><h3>Scree Plot</h3><p>A scree plot is a helpful visualization used to determine the number of principal components you should keep. Data scientists typically use the<strong> “elbow” rule</strong> to determine where the amount of additional explained variance drops sharply, hence finding the optimal number of principal components to retain.</p><p>There are many built-in visualizations for scree plots, but none of them (that we could find) show both the explained variance and cumulative explained variance. That’s why we’ll visualize it from scratch:</p><div class="w-embed"><pre><code class="language-r"># Plot for Explained Variance plot_explained_variance <- ggplot(pca_summary, aes(x = Component)) + geom_bar(aes(y = ExplainedVariance), stat = "identity", fill = "steelblue", color = "black") + geom_text(aes(y = ExplainedVariance, label = paste0(round(ExplainedVariance, 2), "%")), vjust = -0.5, size = 5, color = "#000000") + ylim(0, 101) + labs( title = "Explained Variance by Principal Component", x = "Principal Component", y = "Percentage Explained Variance" ) + theme_minimal() # Plot for Cumulative Explained Variance plot_cumulative_explained_variance <- ggplot(pca_summary, aes(x = Component)) + geom_line(aes(y = CumulativeExplainedVariance), color = "orange", size = 1) + geom_point(aes(y = CumulativeExplainedVariance), color = "orange") + geom_text(aes(y = CumulativeExplainedVariance, label = paste0(round(CumulativeExplainedVariance, 2), "%")), vjust = -0.5, size = 5, color = "#000000", nudge_x = 0.15) + scale_y_continuous(name = "Cumulative Explained Variance (%)") + ylim(0, 101) + labs( title = "Cumulative Explained Variance", x = "Principal Component" ) + theme_minimal() # Arrange plots in a grid grid.arrange( plot_explained_variance, plot_cumulative_explained_variance, ncol = 2, nrow = 1, top = "PCA Variance Explained" )</code></pre></div><figure style="max-width:3452pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187a3_66a0f2c6a3b7f5c4d33ee602_7.webp" loading="lazy" alt=""/></div><figcaption>Image 7 - Explained variance + cumulative explained variance plot</figcaption></figure><p>You can see that the charts are just another way of showcasing the values you already know from a tabular format. </p><p>But, keep an eye on the cumulative percentage of explained variance - 2 components explain ~ 96%, and 3 components explain ~ 99.5%. This means you can visualize them to see the true essence of the Iris dataset in a lower-dimensional space.</p><p>Let’s do that next.</p><h3>2-Dimensional PC Scatter Plot</h3><p>Up first, the two-dimensional charts. Almost all the dataset variance can be explained by the first two principal components. We’ll make a <a href="https://www.appsilon.com/post/ggplot-scatter-plots">scatter plot</a> and change the individual marker color and shape to match the `Species` target variable:</p><div class="w-embed"><pre><code class="language-r">first_two_components <- data.frame(pca_result$x[, 1:2], Species = y) colors <- c("#004B95", "#38812F", "#A30000") shapes <- c(15, 16, 17) ggplot(first_two_components, aes(x = PC1, y = PC2, color = Species)) + geom_point(alpha = 0.8, size = 4, shape = shapes[as.numeric(first_two_components$Species)]) + labs(title = "Iris Data Projected onto the First 2 Principal Components") + scale_color_manual(values = colors) + theme_minimal()</code></pre></div><figure style="max-width:2284pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187a6_66a0f2e47010083f81727b18_8.webp" loading="lazy" alt=""/></div><figcaption>Image 8 - Visualizing PCA results in 2 dimensions</figcaption></figure><p>There’s a clear distinction between the flower species, especially from <em>setosa</em> to the others. Up next, let’s see if adding a third dimension can increase the information quality.</p><h3>3-Dimensional PC Scatter Plot</h3><p>We’ll use the Plotly package to create a 3-dimensional scatter plot. We’ll also modify a couple of things while here - marker symbol, color, and the text displayed when hovering over an individual data point:</p><div class="w-embed"><pre><code class="language-r">first_three_components <- data.frame(pca_result$x[, 1:3], Species = y) colors <- c("#004B95", "#38812F", "#A30000") shapes <- c(15, 16, 17) hover_text <- paste( "<b>Species:", first_three_components$Species, "</b>", "<br>PC1:", first_three_components$PC1, "<br>PC2:", first_three_components$PC2, "<br>PC3:", first_three_components$PC3 ) plot_ly( data = first_three_components, x = ~PC1, y = ~PC2, z = ~PC3, type = "scatter3d", mode = "markers", marker = list(size = 6), text = hover_text, hoverinfo = "text", color = ~Species, colors = colors, symbol = ~Species, symbols = shapes ) %>% layout( title = "Iris Data Projected onto the First 3 Principal Components", scene = list( xaxis = list(title = "PC1"), yaxis = list(title = "PC2"), zaxis = list(title = "PC3") ) )</code></pre></div><figure style="max-width:1094pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc1880b_66a0f3044f7c298778856b02_9.gif" loading="lazy" alt=""/></div><figcaption>Image 9 - Visualizing PCA results in 3 dimensions</figcaption></figure><p>Plotly charts are interactive by default, meaning you can zoom in, and out, rotate them, and generally manipulate them however you see fit. It’s a must-have for 3-dimensional data visualization.</p><p>Adding a third principal component into the mix didn’t add that much information. That’s expected since it only accounts for an additional ~3.5% of variance.</p><h3>Attribute Biplot</h3><p>Let’s now get into a highly specific visualization type - biplot. In plain English, it shows the relationship between principal components and original variables. It provides a way to <strong>interpret PCA results</strong> and understand how the original variables contribute to the principal components.</p><p>Biplot shows the first two principal components on the X and Y axes. Vectors (arrows) represent the original variables. Their direction and length indicate how strongly each variable influences principal components (longer = more). The angle between vectors shows the correlation between variables - the closer they are together, the more correlated they are.</p><p>In R, you can call the `factoextra::fviz_pca_var()` function to visualize a biplot:</p><div class="w-embed"><pre><code class="language-r">fviz_pca_var(pca_result, col.var = "black")</code></pre></div><figure style="max-width:2082pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc18794_66a0f347239b13bc41dd3f18_10.webp" loading="lazy" alt=""/></div><figcaption>Image 10 - Attribute biplot</figcaption></figure><p>As you can see, petal length and width are highly correlated. Sepal length is also quite there, but sepal width is highly individual.</p><h3>Loading Score Plot</h3><p>And finally, let’s take a look at loading scores. <strong>You can think of these as coefficients that show how much each original variable contributes to each principal component</strong>. Some use it as a way to find the most relevant features in the dataset. After all, if the first principal components account for ~ 70% of the variance, it makes sense to see which features contribute the most to this high percentage.</p><p>Loading scores range from -1 to +1. Most of the time you won’t be interested if the value is positive or negative - you’re just looking for the highest absolute value.</p><p>The following <a href="https://www.appsilon.com/post/ggplot2-bar-charts">bar chart</a> shows a 2x2 grid of loading scores for every principal component:</p><div class="w-embed"><pre><code class="language-r">loadings <- as.data.frame(pca_result$rotation) loadings$Variable <- rownames(loadings) loadings_melted <- melt(loadings, id.vars = "Variable", variable.name = "PrincipalComponent", value.name = "LoadingScore") colors <- c("#004B95", "#38812F", "#A30000", "#FFCC33") ggplot(loadings_melted, aes(x = Variable, y = LoadingScore, fill = PrincipalComponent)) + geom_bar(stat = "identity", color = "black") + facet_wrap(~PrincipalComponent, scales = "free", ncol = 2) + scale_y_continuous(limits = c(-1, 1)) + scale_fill_manual(values = colors) + labs( title = "Iris PCA Loading Scores", x = "Variable", y = "Loading Score" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 90, hjust = 1))</code></pre></div><figure style="max-width:2716pxpx" class="w-richtext-align-fullwidth w-richtext-figure-type-image"><div><img src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/672c84d42a6c418b6cc187a9_66a0f369cc22d725c1cd03d8_11.webp" loading="lazy" alt=""/></div><figcaption>Image 11 - PCA loading score plot</figcaption></figure><p>The features petal length, petal width, and sepal length are the most important ones in the first principal component that in itself captures over 70% of the dataset’s variance. The roles are reversed in the second component - there, the sepal width is the key contributor.</p><h2>Summing up R PCA</h2><p>And there you have it - Principal Component Analysis explained in plain English. The basic idea behind the algorithm is simple - reduce the dimensionality of the data by calculating the principal components - one-directional variances of the entire dataset. Combine a couple of them, and you have a low-dimensional representation that accounts for most of the original data.</p><p>You can dive deeper into the mathematics on your own if you like, and we strongly encourage you to do so. R does a fantastic job of hiding all the calculations for you. All you need to do is provide a numerical dataset that has all features centered around 0 with a standard deviation of 1, and has no missing values.</p><p><em>How do you use the results of Principal Component Analysis in R? Is there a visualization type we haven’t covered?</em> <a href="https://go.appsilon.com/shiny4allcommunity?utm_source=community&utm_medium=website&utm_campaign=blog">Join our Slack community and let us know!</a></p><blockquote><em>Looking for a practical example of Data Science in Finance? </em><a href="https://www.appsilon.com/post/appsilon-ceo-filip-stachura-talked-about-data-science-in-finance"><em>Watch our video on successful machine learning projects in Fintech</em></a><em>.</em></blockquote></div></div></div></div><div class="blog-side-wrapper"><div class="blog-form-wrapper"><div class="shadow-xsmall"><div class="slack_banner_wraper"><div class="wrap_flex-h"><h4>Have questions or insights? </h4><div class="spacer-tiny"></div><div class="text-size-tiny">Engage with experts, share ideas and take your data journey to the next level!</div></div><div class="spacer-xsmall"></div><div class="w-layout-hflex button-group"><a href="/contact-us" class="button is-small w-button">Contact Us</a></div></div></div></div><div class="blog-form-wrapper cta w-condition-invisible"><div class="shadow-xsmall"><div class="gxp_banner_wraper"><div class="wrap_flex-h"><h4><span>Is Your Software GxP Compliant?</span></h4><div class="spacer-tiny"></div><div class="text-size-tiny">Download a checklist designed for clinical managers in data departments to make sure that software meets requirements for FDA and EMA submissions.</div><div class="spacer-xsmall"></div><div class="w-layout-hflex button-group"><a href="https://www.appsilon.com/resources/definition-of-done-checklist-for-pharma-teams" class="button is-small w-button">Get the Checklist</a></div></div></div></div></div><div class="shadow-xsmall w-condition-invisible"><div class="gxp_banner_wraper audit"><div class="max-width-small-blog-card"><div class="wrap_flex-h"><h4><span><strong>Ensure Your R and Python Code Meets FDA and EMA Standards</strong></span></h4><div class="spacer-tiny"></div><div class="text-size-tiny">A comprehensive diagnosis of your R and Python software and computing environment compliance with actionable recommendations and areas for improvement.</div><div class="spacer-xsmall"></div><div class="w-layout-hflex button-group"><a href="/services/gxp-audit" class="button is-red is-small w-button">Book the Audit</a></div></div></div></div></div></div></div></div></div></div></article><section class="section_blog-post4-related"><div class="padding-global-19"><div class="container-large-9"><div class="padding-section-large"><div class="header-wrapper is-animation-fade-in"><div class="is-txt-small is-txt-label">Related posts</div><div class="spacer-xsmall"></div><div class="w-layout-hflex flex-block-3"><h5 class="heading-8">Read about similar topics</h5></div><div class="spacer-small"></div><div class="separator"></div><div class="spacer-large"></div></div><div class="blog-post4-related_component"><div class="blog-post4-related_heading-wrapper"><div class="blog-post4-related_heading"><div class="max-width-large"></div></div></div><div class="blog-post4-related_list-wrapper"><div class="blog3-header_featured-blog"><div class="blog-cms-warp w-dyn-list"><div fs-cmsload-mode="load-under" role="list" class="blog-cms-list w-dyn-items"><div role="listitem" class="blog-cms-item w-dyn-item"><a href="/post/llm-quarto-automation" class="fs_nest_link_block w-inline-block"></a><div data-w-id="362d5b06-cb82-037a-cca4-0267cd96bcc9" class="blog-item"><a href="/post/llm-quarto-automation" class="link-block-no-styles w-inline-block"><img alt="" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto.jpg" loading="lazy" sizes="100vw" srcset="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto-p-500.jpg 500w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto-p-800.jpg 800w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto-p-1080.jpg 1080w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto-p-1600.jpg 1600w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67c20b48029338352aeab595_quarto.jpg 1921w" class="blog_item-image"/><div class="spacer-xsmall"></div><div class="w-layout-vflex blog-item-content"><h5 fs-cmsfilter-field="name" fs-cmssort-field="name" class="blog-item-header">LLM + Quarto: Turn One-Off Reports Into Automated Solutions</h5><div class="spacer-xsmall"></div><div class="text-size-small">Generate and automate Quarto reports with LLMs. Build once refine with your team and deploy to Posit Connect for fresh data. </div></div></a><a href="/author/pasza" class="link-block_no-style w-inline-block"><div class="blog_authors_wrapper"><img alt="" loading="lazy" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/65e6046f4e59434820ecece7_Screenshot%202024-03-04%20at%2019.27.08.png" class="blog-author-avatar shadow-medium"/><div fs-cmsfilter-field="tag" class="blog-authors-text">Piotr Pasza Storożenko</div></div></a></div></div><div role="listitem" class="blog-cms-item w-dyn-item"><a href="/post/llm-apps-shiny-python" class="fs_nest_link_block w-inline-block"></a><div data-w-id="362d5b06-cb82-037a-cca4-0267cd96bcc9" class="blog-item"><a href="/post/llm-apps-shiny-python" class="link-block-no-styles w-inline-block"><img alt="" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM.webp" loading="lazy" sizes="100vw" srcset="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM-p-500.webp 500w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM-p-800.webp 800w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM-p-1080.webp 1080w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM-p-1600.webp 1600w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a64ab6cea3d6a0776f02ae_LLM.webp 1920w" class="blog_item-image"/><div class="spacer-xsmall"></div><div class="w-layout-vflex blog-item-content"><h5 fs-cmsfilter-field="name" fs-cmssort-field="name" class="blog-item-header">Building LLM-Powered Applications with Shiny for Python: Practical Insights</h5><div class="spacer-xsmall"></div><div class="text-size-small">Learn how to build flexible LLM apps in Shiny for Python, handle API changes, and keep your project future-proof.</div></div></a><a href="/author/pasza" class="link-block_no-style w-inline-block"><div class="blog_authors_wrapper"><img alt="" loading="lazy" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/65e6046f4e59434820ecece7_Screenshot%202024-03-04%20at%2019.27.08.png" class="blog-author-avatar shadow-medium"/><div fs-cmsfilter-field="tag" class="blog-authors-text">Piotr Pasza Storożenko</div></div></a></div></div><div role="listitem" class="blog-cms-item w-dyn-item"><a href="/post/react-python-r-decison-systems" class="fs_nest_link_block w-inline-block"></a><div data-w-id="362d5b06-cb82-037a-cca4-0267cd96bcc9" class="blog-item"><a href="/post/react-python-r-decison-systems" class="link-block-no-styles w-inline-block"><img alt="" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython.png" loading="lazy" sizes="100vw" srcset="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython-p-500.png 500w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython-p-800.png 800w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython-p-1080.png 1080w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython-p-1600.png 1600w, https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/67a533fdc26fa2b3b5853caf_react%2Bpython.png 1921w" class="blog_item-image"/><div class="spacer-xsmall"></div><div class="w-layout-vflex blog-item-content"><h5 fs-cmsfilter-field="name" fs-cmssort-field="name" class="blog-item-header">Scaling Decision Support Systems: When to Use React, Python, and R</h5><div class="spacer-xsmall"></div><div class="text-size-small">Shiny, React, or Python? Learn how to choose the right stack for building and scaling decision support systems.</div></div></a><a href="/author/pasza" class="link-block_no-style w-inline-block"><div class="blog_authors_wrapper"><img alt="" loading="lazy" src="https://cdn.prod.website-files.com/654fd3ad88635290d9845b9e/65e6046f4e59434820ecece7_Screenshot%202024-03-04%20at%2019.27.08.png" class="blog-author-avatar shadow-medium"/><div fs-cmsfilter-field="tag" class="blog-authors-text">Piotr Pasza Storożenko</div></div></a></div></div></div></div></div></div><div class="blog-post4-related_button-row mobile-landscape"><a href="#" class="button-27 is-secondary w-button">View all</a></div></div></div></div></div></section><section id="Resources" class="section_explore"><section class="section_cta_bottom"><div class="overlay_noise"></div><div class="padding-global"><div class="container-large"><div class="padding-section-large"><div class="w-layout-grid layout253_component_inverted_1"><div class="layout253_content"><div class="max-width-medium"><div class="animation-fade-right"><div class="is-txt-label">Explore Possibilities</div></div><div class="spacer-small-9"></div><div class="animation-fade-right"><h2 class="heading-24"><strong>Share Your Data Goals with Us</strong></h2></div><div class="spacer-small-9"></div><div class="animation-fade-right"><p class="text-size-medium text-color-offwhite-dark-mode">From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.</p></div><div class="spacer-medium-8"></div><a href="/contact-us" class="button w-button">Talk to our Experts</a></div></div></div></div></div></div></section></section></main></div><footer class="footer"><div class="w-layout-blockcontainer container-large w-container"><div id="w-node-_5ce768b3-13ba-8ca2-9f8a-e367287fb3ac-287fb3aa" class="w-layout-layout footer_grid wf-layout-layout"><div id="w-node-_5ce768b3-13ba-8ca2-9f8a-e367287fb3ad-287fb3aa" class="w-layout-cell"><div class="navbar-brand"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/6539655f4ca172cfc5deaad8_Appsilon_logo.svg" loading="lazy" width="127" height="51" alt="" class="is-logo-appsilon"/></div></div><div id="w-node-_5ce768b3-13ba-8ca2-9f8a-e367287fb3d1-287fb3aa" class="w-layout-cell"><div class="footer_content-wrap"><div class="is-txt-medium is-txt-bold"><strong>Company</strong></div><div class="footer-links"><a href="/data-for-good" class="footer_link is-txt-small is-txt-navy-60">Data4Good</a><a href="/ai-research" class="footer_link is-txt-small is-txt-navy-60">AI and Research</a><a href="/blog" class="footer_link is-txt-small is-txt-navy-60">Blog</a><a href="/careers" class="footer_link is-txt-small is-txt-navy-60">Careers</a><a href="/privacy-policy" class="footer_link is-txt-small is-txt-navy-60">Privacy Policy</a><a href="/code-of-conduct" class="footer_link is-txt-small is-txt-navy-60">Code of Conduct</a></div></div></div><div id="w-node-_5ce768b3-13ba-8ca2-9f8a-e367287fb3de-287fb3aa" class="w-layout-cell"><div class="footer_content-wrap"><div class="is-txt-medium is-txt-bold"><strong>Shiny Resources</strong></div><div class="footer-links"><div class="footer-links"><a href="https://shinyconf.appsilon.com/" class="footer_link is-txt-small is-txt-navy-60">Shiny Conference</a><a href="/shiny-demo-gallery" class="footer_link is-txt-small is-txt-navy-60">Demo Gallery </a><a href="/resources/collection" class="footer_link is-txt-small is-txt-navy-60">Shiny Templates</a><a href="/rhinoverse" class="footer_link is-txt-small is-txt-navy-60">Shiny Tools</a><a href="https://github.com/Appsilon/" class="footer_link is-txt-small is-txt-navy-60">Appsilon's GitHub</a></div></div></div></div><div id="w-node-_5ce768b3-13ba-8ca2-9f8a-e367287fb3ee-287fb3aa" class="w-layout-cell"><div class="footer_content-wrap"><div class="is-txt-medium is-txt-bold"><strong>Partnerships</strong></div><div class="footer-links"><div class="footer-links"><a href="/posit-certified-partner" class="footer_link is-txt-small is-txt-navy-60">Posit (formerly RStudio)</a><a href="https://www.dominodatalab.com/partners" class="footer_link is-txt-small is-txt-navy-60">Domino Data Lab</a><a href="https://www.r-bloggers.com/" class="footer_link is-txt-small is-txt-navy-60">R-Bloggers</a><a href="https://python-bloggers.com/" class="footer_link is-txt-small is-txt-navy-60">Python-Bloggers</a></div></div></div></div></div><div class="is-margin-t-24"><div class="copyright"><div class="is-horizontal-wrap"><a href="https://appsilon.com/privacy-policy/" class="is-txt-xsmall is-txt-navy-60">Privacy Policy</a><a href="https://appsilon.com/code-of-conduct/" class="is-txt-xsmall is-txt-navy-60">Code of Conduct</a></div><div class="is-txt-xsmall is-txt-navy-60">Copyrights © appsilon.com All rights reserved.</div><div class="copmany_inforamtion"><div><div class="is-txt-small is-txt-navy-60"><strong>PL: </strong>Appsilon Sp. z o.o.</div><div class="is-txt-small is-txt-navy-60"><strong>VAT ID:</strong> PL5252569920</div></div><div class="is-txt-small is-txt-navy-60">ul. Chmielna 2/31 <br/>00-020 Warszawa</div><div class="is-txt-small is-txt-navy-60">hello@appsilon.com</div></div><div id="w-node-c5bc1998-377b-c9f0-b901-373cf389bede-287fb3aa" class="w-layout-layout quick-stack-3 wf-layout-layout"><div class="w-layout-cell"><a href="https://www.youtube.com/channel/UC6LqpR5qBfNlQp5mVIVsthA" target="_blank" class="w-inline-block"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/652561c667346b69289ea965_Youtube.svg" loading="lazy" alt="" class="sm_icon"/></a></div><div class="w-layout-cell"><a href="https://github.com/Appsilon/" target="_blank" class="w-inline-block"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/652561c667346b69289ea969_GitHub.svg" loading="lazy" alt="" class="sm_icon"/></a></div><div class="w-layout-cell"><a href="https://www.linkedin.com/company/appsilon" target="_blank" class="w-inline-block"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/652561c667346b69289ea968_LinkedIn.svg" loading="lazy" alt="" class="sm_icon"/></a></div><div class="w-layout-cell"><a href="https://twitter.com/appsilon" target="_blank" class="w-inline-block"><div class="code-embed-2 w-embed"><svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17.1761 4H19.9362L13.9061 10.7774L21 20H15.4456L11.0951 14.4066L6.11723 20H3.35544L9.80517 12.7508L3 4H8.69545L12.6279 9.11262L17.1761 4ZM16.2073 18.3754H17.7368L7.86441 5.53928H6.2232L16.2073 18.3754Z" fill="CurrentColor"/> </svg></div></a></div><div class="w-layout-cell"><a href="https://www.facebook.com/appsilondatascience/" class="w-inline-block"><img src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/652561c667346b69289ea966_Facebook.svg" loading="lazy" alt="" class="sm_icon"/></a></div><div class="w-layout-cell"><a href="https://bsky.app/profile/appsilon.bsky.social" class="w-inline-block"><div class="icon-1x1-small w-embed"><svg width="28" height="28" viewBox="0 0 95 85" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M47.466 38.5019C43.8802 31.475 34.1536 18.3499 25.0994 11.8902C16.4261 5.70202 13.1093 6.76734 10.9583 7.76474C8.44826 8.92078 8 12.8195 8 15.109C8 17.3985 9.23262 33.9233 10.0619 36.6662C12.7513 45.7785 22.2762 48.8612 31.061 47.8638C31.5093 47.7958 31.9575 47.7278 32.4282 47.6825C31.9799 47.7505 31.5093 47.8185 31.061 47.8638C18.1969 49.7906 6.74526 54.528 21.7602 71.4158C38.255 88.6885 44.3734 67.721 47.5116 57.0677C50.6492 67.6988 54.2575 87.9184 72.9484 71.4158C87.0009 57.0677 76.8032 49.7911 63.939 47.8638C63.4907 47.8185 63.0201 47.7505 62.5718 47.6825C63.0425 47.7505 63.4907 47.7958 63.939 47.8638C72.7242 48.8612 82.2711 45.7784 84.9381 36.6662C85.7449 33.9007 87 17.3986 87 15.109C87 12.8194 86.5518 8.92085 84.0417 7.76474C81.8678 6.76738 78.5732 5.70202 69.9006 11.8902C60.7792 18.373 51.0522 31.4746 47.4672 38.5019H47.466Z" fill="#5E717F"/> </svg></div></a></div></div></div></div></div></footer><div fs-cmsnest-collection="tags" fs-cmsnest-element="template-reference" class="collection-list-wrapper-2 w-dyn-list"><div role="list" class="collection-list-9 w-dyn-items"><div role="listitem" class="w-dyn-item"><a href="/blog-tags/r" class="w-inline-block"></a><div>r</div></div><div role="listitem" class="w-dyn-item"><a href="/blog-tags/data-visualization" class="w-inline-block"></a><div>data visualization</div></div><div role="listitem" class="w-dyn-item"><a href="/blog-tags/ai-research" class="w-inline-block"></a><div>ai&research</div></div></div></div><script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?site=6525256482c9e9a06c7a9d3c" type="text/javascript" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script><script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/js/webflow.schunk.b7cad701f94860c2.js" type="text/javascript"></script><script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/js/webflow.schunk.f63201befcb989a8.js" type="text/javascript"></script><script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c/js/webflow.0abac993.de03907c931440b4.js" type="text/javascript"></script><script src="https://js.usebasin.com/v2.0.3.min.js" async></script> <script src="https://www.google.com/recaptcha/api.js?render=6Les66kUAAAAANyLrgkl7iuN4JUpNlB5upaMovI4"></script> <!-- Start of HubSpot Embed Code --> <script type="text/javascript" id="hs-script-loader" async defer src="//js.hs-scripts.com/4645024.js"></script> <!-- End of HubSpot Embed Code --> <script> function fetchAndDisplayGists() { document.querySelectorAll('script[src^="https://gist.github.com/"]').forEach(script => { const gistId = script.src.split('/').pop().replace('.js', ''); fetch('https://api.github.com/gists/' + gistId) .then(response => response.json()) .then(data => { const content = data.files[Object.keys(data.files)[0]].content; const container = document.createElement('div'); container.classList.add('gist-content'); container.setAttribute('data-gist-id', gistId); container.innerHTML = '<pre><code>' + content + '</code></pre>'; script.outerHTML = container.outerHTML; }) .catch(error => console.error('Error fetching gist:', error)); }); } fetchAndDisplayGists(); </script> <style> .grecaptcha-badge { visibility: hidden !important; } </style> <style> iframe { border-width: 0px; border-style: solid; border-color: initial; border-image: initial; width: 100%; min-height: 15rem; } w-richtext figure { max-width: 100%; position: relative; } img { height: auto !important; } hljs { color: #000; } code.hljs { padding: 3px 5px; background-color: #dae2ee; border-radius: 0.3rem; font-size: 0.9rem; } pre { word-wrap: normal; background-color: #dae2ee; color: #000; border-radius: 0.5rem; font-family: Consolas,Monaco,andale mono,ubuntu mono,monospace; line-height: 1.5; overflow: auto; padding: 1.6rem; text-align: left; white-space: pre; word-break: normal; word-spacing: normal; } ol { margin-top: 0rem; margin-bottom: 0rem; padding-left: 1.5rem; } .w-code-block { margin: unset; background-color: #dae2ee !important; } </style> <script> (async () => { await new Promise(resolve => { setTimeout(resolve, 1000); // Delay execution to let other tasks complete }); async function replaceGistScripts() { document.querySelectorAll('script[src^="https://gist.github.com/"]').forEach(script => { const gistId = script.src.split('/').pop().replace('.js', ''); const iframe = document.createElement('iframe'); iframe.classList.add('gist-iframe'); iframe.setAttribute('data-gist-id', gistId); iframe.setAttribute('src', 'https://gist.github.com/' + gistId + '.pibb'); iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts'); script.parentNode.replaceChild(iframe, script); }); } replaceGistScripts(); })(); </script> <script src="https://hubspotonwebflow.com/assets/js/form-124.js" type="text/javascript" integrity="sha384-bjyNIOqAKScdeQ3THsDZLGagNN56B4X2Auu9YZIGu+tA/PlggMk4jbWruG/P6zYj" crossorigin="anonymous"></script><script src="https://cdn.prod.website-files.com/6525256482c9e9a06c7a9d3c%2F6470f5217e03b0faa8a404de%2F652954d0206d2232bbeb785f%2Fhs_trackcode_4645024-1.0.6.js" type="text/javascript"></script></body></html>