Nova is a Austrian Paraglider Company who have been designing paragliders since the early days of the sport. This analysis aims to collect the specification of each gilder in the range and Visualise the compiled data and Specific glider data. There are two tables for each glider, specifications and materials, both will be combined into the overall Interactive table.

Collecting specification and materials data tables for each paraglider in the range.

To create a complete data frame of glider data which allows paragliders to be compared on various performance metrics.

**Issues when creating the data frame*

Each glider specification table is slightly different, metrics are not standard and some are absent, The first aim is to standardise all the specification metrics for each glider and the metrics used for each glider.

General method used to obtain, clean and organise the data

# PRION GLIDER ----
# Specify the URL of the webpage
url_prion5 <- "https://www.nova.eu/en/gliders/prion-5/#c13445"

# Read the webpage
prion_page <- read_html(url_prion5)

# Extract the table data with class "content table"
prion_table <- html_table(html_nodes(prion_page, "table.contenttable"))


# Table listing glider componenet material
df_prion5_materials <- prion_table[[2]] %>% set_names(c("Component", "Material"))
df_prion5_materials
df_prion5_materials_pivoted <- df_prion5_materials %>%
  pivot_wider(names_from = Component, values_from = Material)


# remove the colons from the colnames

colnames(df_prion5_materials_pivoted) <- gsub(":", "", colnames(df_prion5_materials_pivoted))

# Specifications table

df_prion5 <- prion_table[[1]]

# name an remove columns
colnames(df_prion5) <- paste("Prion5", colnames(df_prion5), sep = "_")
colnames(df_prion5)[1] <- "Features"
colnames(df_prion5)[2] <- "Units"
df_prion5 <- df_prion5 %>% select(-Units)
df_prion5
# Pivot df to list products as rows and features as columns
df_prion_pivoted <- df_prion5 %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_prion_pivoted <- df_prion_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)
df_prion_pivoted
# Remove unwanted cols

df_prion_pivoted<- df_prion_pivoted %>% select(-`Min. chord`,-`Line diameter`,-`Suitable for schooling`,-`Min. chord`)

# Remove comma and replace with decimal point

numerical_cols <- c( "Number of cells","Projected span","Projected area",
                     "Projected aspect ratio" ,"Flat span","Flat area","Flat aspect ratio",
                   "Line length"    , "Total line length","Max. chord", "Weight" )


# Changing cols with numerical values to numerical data type from char

df_prion_pivoted <- df_prion_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))



# Table listing glider componenet material
df_prion5_materials <- prion_table[[2]] %>% set_names(c("Component", "Material"))




df_prion5_materials_pivoted <- df_prion5_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# Remove the colons from the colnames

colnames(df_prion5_materials_pivoted) <- gsub(":", "", colnames(df_prion5_materials_pivoted))


# Combine gilder spec and glider materials df

total_nova_df <- df_prion_pivoted %>%
  bind_cols(df_prion5_materials_pivoted)

total_nova_df

Read in the second glider, pivot and clean the data and combine into the data frame

# AONIC GLIDER----


url_aonic <- "https://www.nova.eu/en/gliders/aonic-light/#c14592"

# Read the webpage
aonic_page <- read_html(url_aonic)

# Extract the table data with class "content table"
aonic_table <- html_table(html_nodes(aonic_page, "table.contenttable"))


# Table listing glider componenet material
df_aonic_materials <-aonic_table[[2]] %>% set_names(c("Component","Material"))

df_aonic_materials_pivoted <- df_aonic_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_aonic_materials_pivoted) <- gsub(":", "", colnames(df_aonic_materials_pivoted))

# Specifications table

df_aonic_spec <- aonic_table[[1]]

# remove empty last colunm
df_aonic_spec <-df_aonic_spec[,1:6]

# name an remove columns
colnames(df_aonic_spec) <- paste("Aonic", colnames(df_aonic_spec), sep = "_")
colnames(df_aonic_spec)[1] <- "Features"
colnames(df_aonic_spec)[2] <- "Units"
df_aonic_spec <- df_aonic_spec %>% select(-Units)

# pivot df to list products ass rows and features as columns
df_aonic_pivoted <- df_aonic_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_aonic_pivoted <- df_aonic_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

df_aonic_pivoted <- df_aonic_pivoted %>% select(-`Line diameter`)
# Colnames do not match

# checking col names inconsistent col names
#colnames(total_nova_df)
#colnames(df_aonic_pivoted)

# chaning to common col names
df_aonic_pivoted <- df_aonic_pivoted %>%
  rename("Certified weight-range" = "Certified take off weight")

# Introducing a column of NA's for the missing total line lenght col for the aonic glider
df_aonic_pivoted <-df_aonic_pivoted %>%
  mutate(`Total line length` = NA)

#setdiff(colnames(total_nova_df), colnames(df_pivoted))


# remove comma and replace with decimal point
numerical_cols <-c( "Number of cells","Projected span" ,"Projected area"  ,"Projected aspect ratio",
                    "Flat span",    "Flat area"  ,"Flat aspect ratio",  "Line length",
                    "Total line length",  "Max. chord","Weight")


# Changing cols with numercal values to numerical data type from char

df_aonic_pivoted <- df_aonic_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df

# Colnames are nit consistant with previous glider, adjusting to keep material columns consistent

df_aonic_materials_pivoted <-df_aonic_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


aonic_total_df <- df_aonic_pivoted %>%
  bind_cols(df_aonic_materials_pivoted)

# Bind the current glider to the existing complete df


# check col names are the same
setdiff(colnames(total_nova_df), colnames(aonic_total_df))
## character(0)
total_nova_df <- total_nova_df %>%
  bind_rows(aonic_total_df)
total_nova_df

Third Glider: Deal with missing data in absent specification for the ion glider.

# Ion Glider ----

url_ion <- "https://www.nova.eu/en/gliders/ion-7/#c14996"

# Read the webpage
ion_page <- read_html(url_ion)

# Extract the table data with class "content table"
ion_table <- html_table(html_nodes(ion_page, "table.contenttable"))


# Table listing glider componenet material
df_ion_materials <-ion_table[[2]] %>% set_names(c("Component","Material"))

df_ion_materials_pivoted <- df_ion_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_ion_materials_pivoted) <- gsub(":", "", colnames(df_ion_materials_pivoted))

# Specifications table

df_ion_spec <- ion_table[[1]]

# remove empty last colunm if required
#df_glider_spec <-df_glider_spec[,1:6]

# name an remove columns
colnames(df_ion_spec) <- paste("Ion", colnames(df_ion_spec), sep = "_")
colnames(df_ion_spec)[1] <- "Features"
colnames(df_ion_spec)[2] <- "Units"
df_ion_spec <- df_ion_spec %>% select(-Units)

# pivot df to list products ass rows and features as columns
df_ion_pivoted <- df_ion_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_ion_pivoted <- df_ion_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

#df_pivoted <- df_pivoted %>% select(-`Line diameter`)
# Colnames do not match

# checking col names inconsistent col names
#colnames(total_nova_df)
#colnames(df_ion_pivoted)

# chaning to common col names
df_ion_pivoted <- df_ion_pivoted %>%
  rename("Certified weight-range" = "Certified take off weight")

# Introducing a column of NA's for the missing total line lenght col for the aonic glider
df_ion_pivoted <-df_ion_pivoted %>%
  mutate(`Projected span` = NA)

# remove comma and replace with decimal point
numerical_cols <-c( "Number of cells","Projected span" ,"Projected area"  ,"Projected aspect ratio",
                    "Flat span",    "Flat area"  ,"Flat aspect ratio",  "Line length",
                    "Total line length",  "Max. chord","Weight")


# Changing cols with numercal values to numerical data type from char

# remove min chord col
#df_pivoted <-df_pivoted %>%select(-`Min. chord`)

df_ion_pivoted <- df_ion_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df

# consistant colnames

df_ion_materials_pivoted <-df_ion_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


total_ion_df <- df_ion_pivoted %>%
  bind_cols(df_ion_materials_pivoted)

# Large size has NA's to be replaced with known values

# Find the row index of the specific glider for the number of cells col
row_index <- which(total_ion_df$Glider == "Ion_L")
total_ion_df$`Number of cells`[row_index] <- 51

# Find the row index of the specific glider for the proj aspect ratio col
row_index <- which(total_ion_df$Glider == "Ion_L")
total_ion_df$`Projected aspect ratio`[row_index] <- 3.86

row_index <- which(total_ion_df$Glider == "Ion_L")
total_ion_df$`Flat aspect ratio`[row_index] <- 5.17

# Bind the current glider to the existing complete df
# check df's for col name issues
#setdiff(colnames(total_nova_df), colnames(total_ion_df))

total_nova_df <- total_nova_df %>%
  bind_rows(total_ion_df)
total_nova_df

Next glider, Mentor..

# MENTOR GLIDER ----

url_mentor <- "https://www.nova.eu/en/gliders/mentor-7/#c14065"

  # Read the webpage
  mentor_page <- read_html(url_mentor)

# Extract the table data with class "content table"
mentor_table <- html_table(html_nodes(mentor_page, "table.contenttable"))


# Table listing glider componenet material
df_mentor_materials <-mentor_table[[2]] %>% set_names(c("Component","Material"))

df_mentor_materials_pivoted <- df_mentor_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_mentor_materials_pivoted) <- gsub(":", "", colnames(df_mentor_materials_pivoted))

# Spec table
df_mentor_spec <- mentor_table[[1]]

# remove empty last colunm if required
#df_glider_spec <-df_glider_spec[,1:6]

# name an remove columns
colnames(df_mentor_spec) <- paste("Mentor 7", colnames(df_mentor_spec), sep = "_")
colnames(df_mentor_spec)[1] <- "Features"
colnames(df_mentor_spec)[2] <- "Units"
df_mentor_spec <- df_mentor_spec %>% select(-Units,-`Mentor 7_XXS*`,-`Mentor 7_`)


# pivot df to list products ass rows and features as columns
df_mentor_pivoted <- df_mentor_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_mentor_pivoted <- df_mentor_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

df_mentor_pivoted <- df_mentor_pivoted %>% select(-`Line diameter`)
# Colnames do not match

# checking col names inconsistent col names
#setdiff(colnames(total_nova_df), colnames(df_mentor_pivoted))

# changing to common col names
df_mentor_pivoted <- df_mentor_pivoted %>%
  rename("Certified weight-range" = "Certified take off weight")

# remove last row -

df_mentor_pivoted <-df_mentor_pivoted[1:3,]


setdiff(colnames(total_nova_df), colnames(df_mentor_pivoted))
## [1] "Total line length" "Leading edge"      "Top surface"      
## [4] "Lower surface"     "Profile ribs"      "Main lines"       
## [7] "Gallery lines"     "Brake lines"       "Risers"
# Remove numbers and brackets from the column namesgsub("\\[\\d+\\] ", "", colnames(df_pivoted))

# remove comma and replace with decimal point
numerical_cols <-c(   "Number of cells",             "Projected span",
                      "Projected area",              "Projected aspect ratio",      "Flat span",
                      "Flat area",                   "Flat aspect ratio",           "Line length",
                      "Max. chord",                  "Weight")

# Changing cols with numercal values to numerical data type from char


df_mentor_pivoted <- df_mentor_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df

# Consistant colnames

df_mentor_materials_pivoted <-df_mentor_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


total_mentor_df <- df_mentor_pivoted %>%
  bind_cols(df_mentor_materials_pivoted)

#setdiff(colnames(total_nova_df), colnames(total_df))

total_nova_df <- total_nova_df %>%
  bind_rows(total_mentor_df)
total_nova_df
# remove the ion sie large glider - no data 

total_nova_df <- total_nova_df[total_nova_df$Glider != "Mentor 7_L*", ]
total_nova_df

Current list of gliders added to the overall data frame:

unique(total_nova_df$Glider)
##  [1] "Prion5_XXS"  "Prion5_XS"   "Prion5_S"    "Prion5_M"    "Prion5_L"   
##  [6] "Aonic_XXS"   "Aonic_XS"    "Aonic_S"     "Aonic_M"     "Ion_XXS"    
## [11] "Ion_XS"      "Ion_S"       "Ion_M"       "Ion_L"       "Mentor 7_XS"
## [16] "Mentor 7_S"  "Mentor 7_M"

Next Glider .. The Phantom

# PHANTOM GLIDER ----

url_phantom <- "https://www.nova.eu/en/gliders/phantom/#c9376"

# Read the webpage
phantom_page <- read_html(url_phantom)

# Extract the table data with class "content table"
phantom_table <- html_table(html_nodes(phantom_page, "table.contenttable"))


# Table listing glider componenet material
df_phantom_materials <-phantom_table[[2]] %>% set_names(c("Component","Material"))

df_phantom_materials_pivoted <- df_phantom_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_phantom_materials_pivoted) <- gsub(":", "", colnames(df_phantom_materials_pivoted))

# col name bottom surface becomes lower surface to match col name in tibble

df_phantom_materials_pivoted <- df_phantom_materials_pivoted %>%
  rename("Lower surface" = "Bottom surface")


# Spec table
df_phantom_spec <- phantom_table[[1]]

# remove empty last colunm if required
#df_glider_spec <-df_glider_spec[,1:6]

# name an remove columns
colnames(df_phantom_spec) <- paste("Phantom", colnames(df_phantom_spec), sep = "_")
colnames(df_phantom_spec)[1] <- "Features"
colnames(df_phantom_spec)[2] <- "Units"
df_phantom_spec <- df_phantom_spec %>% select(-Units)


# pivot df to list products ass rows and features as columns
df_phantom_spec_pivoted <- df_phantom_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_phantom_spec_pivoted <- df_phantom_spec_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

df_phantom_spec_pivoted <- df_phantom_spec_pivoted %>% select(-`Min. chord`)
# Colnames do not match

# checking col names inconsistent col names
# Should only be material col names as ouput now.
#setdiff(colnames(total_nova_df), colnames(df_phantom_spec_pivoted))



# Remove numbers and brackets from the column namesgsub("\\[\\d+\\] ", "", colnames(df_pivoted))

# remove comma and replace with decimal point
numerical_cols <-c(   "Number of cells",             "Projected span",
                      "Projected area",              "Projected aspect ratio",      "Flat span",
                      "Flat area",                   "Flat aspect ratio",           "Line length",
                      "Max. chord", "Total line length",                 "Weight")

# Changing cols with numercal values to numerical data type from char


df_phantom_spec_pivoted <- df_phantom_spec_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df

# consistant colnames

df_phantom_materials_pivoted <-df_phantom_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


total_phantom_df <- df_phantom_spec_pivoted %>%
  bind_cols(df_phantom_materials_pivoted)


# join new glider to tibble
total_nova_df <- total_nova_df %>%
  bind_rows(total_phantom_df)

Next the Sector Glider

# SECTOR GLIDER ----

url_sector <- "https://www.nova.eu/en/gliders/sector/#c10348"

# Read the webpage
sector_page <- read_html(url_sector)

# Extract the table data with class "content table"
sector_table <- html_table(html_nodes(sector_page, "table.contenttable"))


# Table listing glider componenet material
df_sector_materials <-sector_table[[2]] %>% set_names(c("Component","Material"))

df_sector_materials_pivoted <- df_sector_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_sector_materials_pivoted) <- gsub(":", "", colnames(df_sector_materials_pivoted))

# col name bottom surface becomes lower surface to match col name in tibble

df_sector_materials_pivoted <- df_sector_materials_pivoted %>%
  rename("Lower surface" = "Bottom surface")


df_sector_materials_pivoted <-df_sector_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


# Spec table
# different to other glider specifacation tables with colnames "X1", "X2 etc
df_sector_spec <- sector_table[[1]]%>%select(c("X1","X3","X6","X7","X8")) %>%
                                set_names(c("","XS","S","M","L"))

# remove first row

df_sector_spec <- df_sector_spec[2:16,]

# remove empty last colunm if required
#df_glider_spec <-df_glider_spec[,1:6]


# name an remove columns
colnames(df_sector_spec) <- paste("Sector", colnames(df_sector_spec), sep = "_")
colnames(df_sector_spec)[1] <- "Features"



# pivot df to list products ass rows and features as columns
df_sector_spec_pivoted <- df_sector_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_sector_spec_pivoted <- df_sector_spec_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

df_sector_spec_pivoted <- df_sector_spec_pivoted %>% select(-`Min. chord`)
# Colnames do not match

# checking col names inconsistent col names
# Should only be material col names as ouput now.



# Remove numbers and brackets from the column names
#colnames(df_sector_spec_pivoted)
# remove comma and replace with decimal point
numerical_cols <-c(   "Number of cells",             "Projected span",
                      "Projected area",              "Projected aspect ratio",      "Flat span",
                      "Flat area",                   "Flat aspect ratio",           "Line length",
                      "Max. chord", "Total line length",                 "Weight")

# Changing cols with numercal values to numerical data type from char


df_sector_spec_pivoted <- df_sector_spec_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df


total_sector_df <- df_sector_spec_pivoted %>%
  bind_cols(df_sector_materials_pivoted)



total_nova_df <- total_nova_df %>%
  bind_rows(total_sector_df)

Example of cleaned, joined and pivoted glider data frame to be added to overall data frame

total_sector_df

The Xenon glider

# XENON GLIDER----

url_xenon <- "https://www.nova.eu/en/gliders/xenon/#c14995"

# Read the webpage
xenon_page <- read_html(url_xenon)

# Extract the table data with class "content table"
xenon_table <- html_table(html_nodes(xenon_page, "table.contenttable"))


# Table listing glider componenet material
df_xenon_materials <-xenon_table[[2]] %>% set_names(c("Component","Material"))

df_xenon_materials_pivoted <- df_xenon_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_xenon_materials_pivoted) <- gsub(":", "", colnames(df_xenon_materials_pivoted))


df_xenon_materials_pivoted <-df_xenon_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")


# Spec table
# different to other glider specifacation tables with colnames "X1", "X2 etc
df_xenon_spec <- xenon_table[[1]]

# name glider features
colnames(df_xenon_spec)[1] <- "Features"
colnames(df_xenon_spec)[2] <- "units"

#remove units col, remane glider sizes to be consistent with other gliders tech sheets

df_xenon_spec %>%select(c("Features","units","17","18","20","22")) %>%
  set_names(c("Features","units","XS","S","M","L"))
# name an remove columns
colnames(df_xenon_spec) <- paste("Xenon", colnames(df_xenon_spec), sep = "_")
colnames(df_xenon_spec)[1] <- "Features"

# remove units col
df_xenon_spec <- df_xenon_spec %>% select(-Xenon_units)

# pivot df to list products ass rows and features as columns
df_xenon_spec_pivoted <- df_xenon_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_xenon_spec_pivoted <- df_xenon_spec_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)

# Colnames do not match

# checking col names inconsistent col names
# Should only be material col names as ouput now.
#setdiff(colnames(total_nova_df), colnames(df_xenon_spec_pivoted))



# remove comma and replace with decimal point
numerical_cols <-c(   "Number of cells",             "Projected span",
                      "Projected area",              "Projected aspect ratio",      "Flat span",
                      "Flat area",                   "Flat aspect ratio",           "Line length",
                      "Max. chord", "Total line length",                 "Weight")

# Changing cols with numercal values to numerical data type from char


df_xenon_spec_pivoted <- df_xenon_spec_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df


total_xenon_df <- df_xenon_spec_pivoted %>%
  bind_cols(df_xenon_materials_pivoted)


total_nova_df <- total_nova_df %>%
  bind_rows(total_xenon_df)
total_nova_df

The doubleskin Glider

# doubleskin4

url_doubleskin <- "https://www.nova.eu/en/gliders/doubleskin/#c11943"

# Read the webpage
doubleskin_page <- read_html(url_doubleskin)

# Extract the table data with class "content table"
doubleskin_table <- html_table(html_nodes(doubleskin_page, "table.contenttable"))


# Table listing glider componenet material
df_doubleskin_materials <-doubleskin_table[[2]] %>% set_names(c("Component","Material"))

df_doubleskin_materials_pivoted <- df_doubleskin_materials %>%
  pivot_wider(names_from = Component, values_from = Material)

# remove the colons from the colnames

colnames(df_doubleskin_materials_pivoted) <- gsub(":", "", colnames(df_doubleskin_materials_pivoted))


df_doubleskin_materials_pivoted <-df_doubleskin_materials_pivoted %>% select(-`Profile ribs (unsuspended)`) %>%
  rename("Profile ribs"="Profile ribs (suspended)")
 # rename("Profile ribs"="Profile ribs (suspended)")


# Spec table
# different to other glider specifacation tables with colnames "X1", "X2 etc
df_doubleskin_spec <- doubleskin_table[[1]]


#remove units col, rename glider sizes to be consistent with other gliders tech sheets
# colnames labelled X1 - X5

df_doubleskin_spec <- doubleskin_table[[1]] %>%
  set_names(c("Features","units","17","20","23")) %>%select(-units)


# name an remove columns
colnames(df_doubleskin_spec) <- paste("Doubleskin", colnames(df_doubleskin_spec), sep = "_")
colnames(df_doubleskin_spec)[1] <- "Features"


# pivot df to list products ass rows and features as columns
df_doubleskin_spec_pivoted <- df_doubleskin_spec %>%
  pivot_longer(cols = -Features, names_to = "Glider", values_to = "Values")

# Pivot the data frame again to use "Features" as the new column names
df_doubleskin_spec_pivoted <- df_doubleskin_spec_pivoted %>%
  pivot_wider(names_from = Features, values_from = Values)


#colnames(df_doubleskin_spec_pivoted)

# remove comma and replace with decimal point
numerical_cols <-c(                        "Number of cells",             "Projected span",             
 "Projected area",              "Projected aspect ratio",      "Flat span",                  
 "Flat area",                   "Flat aspect ratio",           "Line length",                
 "Total line length",           "Max. chord",                  "Min. chord",                 
 "Weight"                          )

# Changing cols with numercal values to numerical data type from char



df_doubleskin_spec_pivoted <- df_doubleskin_spec_pivoted %>%
  mutate(across(all_of(numerical_cols), ~as.numeric(gsub(",", "\\.", .))))


# Combine gilder spec and glider materials df
df_doubleskin_spec_pivoted <-df_doubleskin_spec_pivoted %>% select(-"Min. chord")

total_doubleskin_df <- df_doubleskin_spec_pivoted %>%
  bind_cols(df_doubleskin_materials_pivoted)

# add new glider to dataframe
total_nova_df <- total_nova_df %>%
  bind_rows(total_doubleskin_df)
total_nova_df

Rename Column names in final data frame, remove columns with a lot of missing or conflicting data

# Shorten longer col names Remove colums with missing data / confilting info


total_nova_df <- total_nova_df %>% select(-`Line diameter`,-`Certified weight-range`,-`Recommended take off weight`,`Certified take off weight`) %>%
  rename("EN" = "Certification (EN/LTF)")%>%
  rename("Cells" = "Number of cells") %>%
  rename("Proj_Span" = "Projected span") %>%
  rename("Proj_Area" = "Projected area") %>%
  rename("Proj_AR" = "Projected aspect ratio") %>%
  rename("Flat_AR" = "Flat aspect ratio") 

# for plot legend Change facet to EN certification
total_nova_df <- total_nova_df%>%
  mutate(EN = ifelse(startsWith(EN, "EN "), EN, paste("EN", EN, sep = " ")))

row_index <- which(total_nova_df$Glider == "Doubleskin_20")
total_nova_df$`EN`[row_index] <- "EN A"

row_index <- which(total_nova_df$Glider == "Doubleskin_23")
total_nova_df$`EN`[row_index] <- "EN A"

Filter the Columns for the final interactive table.

selected_nova_tbl <- total_nova_df %>%
  select("Glider","EN", "Cells", "Flat_AR", "Flat span","EN","Weight","Max. chord","Top surface","Lower surface","Main lines","Line length", "Main lines" ,"Gallery lines", "Brake lines","Risers")

Exploratory Data Analysis:

Inspect the final data frame

plot_intro(selected_nova_tbl)

plot_missing(selected_nova_tbl)

Histograms of the numeric data

plot_histogram(selected_nova_tbl)

plot_boxplot(selected_nova_tbl,by="Flat span")

plot_boxplot(selected_nova_tbl,by="Flat_AR")

plot_boxplot(selected_nova_tbl,by="Max. chord")

Correlation Matrix

Higher performance gliders have more cells, higher aspect ratio and longer span.

  • The EN D class of glider is highly positively correlated with Flat aspect ratio, wing span, line length and number of cells key indicators of paraglider performance. Higher classes of gliders are negatively correlated with Max chord.

  • Lower performance of gliders such as the A gliders are negatively correlated with aspect ratio and cells, weight. Positively correlated with Max chord as lower performance gliders are wider from leading to trailing edge.

corr_data <-total_nova_df%>% select("Flat_AR", "Weight","EN","Cells",
                                    "Proj_Area","Flat span","Line length", "Max. chord"
                                    )
plot_correlation(corr_data, maxcat = 10L)

Visualise

Visualise he entire range of gliders by key performance metrics on a single plot, with additional glider specifications displayed by tooltip

Create a interactive table to filter and explore all gliders, specifications and materials used.

flat_metrics_three_dim_plot <- selected_nova_tbl %>%select("Glider", "Cells", "Flat_AR", "Flat span","EN","Weight","Max. chord")
plot_ly(data = selected_nova_tbl, x = ~Flat_AR, y = ~`Flat span`, z = ~Cells,
        text = ~paste("Glider: ", Glider,",EN:", EN, "<br>Cells: ", Cells, "<br>Flat_AR: ", Flat_AR,"<br>Flat Span: ", `Flat span`, "<br>Weight: ", Weight,"<br>Max chord", `Max. chord`),
        color = ~as.factor(EN),
        type = "scatter3d",
        mode = "markers") %>%
  layout(scene = list(xaxis = list(title = 'Flat_AR'),yaxis = list(title = 'Flat Span'),zaxis = list(title = 'Cells')),
         margin = list(l = 0, r = 0, b = 0, t = 0),  legend = list(x = 1, y = 0.1),title = list(text = "EN"))  

Specific glider data

Explore full range of specifications in a single 2D plot

h <- ggplot(selected_nova_tbl, 
            aes(x = `Flat span`, y = Cells, fill = Weight,color = Flat_AR, size =Flat_AR,  text = paste("Cells: ", Cells,"<br>Weight: ", Weight,"<br>Flat Span:", `Flat span`,  "<br>Flat AR:", `Flat_AR`,  "<br>",EN,"<br>Max chord ",`Max. chord`))) +
  
  geom_point(alpha = 0.7) +
  scale_size(range = c(5, 15), name = "") +
  scale_fill_viridis_c(option = "plasma", direction = 1) +
  scale_color_viridis_c(option = "turbo")+
  theme(legend.position = "right") +
  facet_wrap(~Glider, scales = "free_x", ncol = 5)+
  scale_x_continuous(expand = expansion(mult = c(0.1, 0.5))) +  
  scale_y_continuous(expand = expansion(mult = c(0.1, 0.5))) +
  ggtitle("Nova Glider Spec 2024") +
  xlab("Flat Span")+
 labs(color = "Flat AR")
h <- ggplotly(h, tooltip = "text", height = 1000, width = 1000)
h

Interactive table

Glider Specification table to explore full Glider dataset, filter by weight etc, materials used etc.

datatable( 
          selected_nova_tbl, class = 'cell-border stripe',
          caption = 'Table 1:Nova Paraglider Specifications 2024.'
          )