I am checking the capabilities of the UMAP dimensionality reduction algorithm, I am not sure whether the approach I am using is valid and does not violate the rules/limitations of this algorithm.

Purpose: visualization (and subsequent grouping) of articles in 3D space based on their thematic connections (words) in the titles/text of these articles.

Steps taken:

  1. text cleaning ; normalization; stopwords; stemming; etc.
  2. 1 hot-encoding;
  3. construction of the Jaccard distance matrix (based on 1h-e data);
  4. UMAP (input matrix from point 3) (umap using Euclidean distance);
  5. Visualization; grouping; further analysis. (not included)

If I understand the UMAP documentation correctly, it also allows the direct use of the Jaccard distance matrix without using the Euclidean distance, but these results, in my opinion (pictorial assessment of the results - proximity of points of related titles), do not separate groups of units as clearly as is visible in the case of using jaccard->euclides .

This raises my question: whether such use will not violate the theoretical assumptions of this algorithm and can be a correctly applied approach, or should I not use it in this way? I've included the R code, charts, and comparison tables below.

I will be grateful for a detailed statement and also for other tips to build the most appropriate solution. Thanks!


    extract <- data.frame(
      title = c(
        "Scheana Shay Unveils Tom Schwartz’s Vegas Kiss on ‘Vanderpump Rules’",
        "Vanessa Marano: In-Depth Look at the ‘Switched at Birth’ Star",
        "What Lies Ahead in Stranger Things Season 5 for Fans",
        "Ariana Madix Acquires $1.6M LA Residence Post Split with Tom Sandoval",
        "Kyle and Claire’s Romance Encounters Hurdles in The Young and the Restless",
        "Twists and Turns in The Bold and the Beautiful Early April Installments",
        "Don Mancini Set to Debut New Film in the Chucky Franchise",
        "Steve Martin Contemplates the Fleeting Nature of Fame and Comedy",
        "Remembering Daytime TV Icon Jennifer Leak Who Passed Away at 76",
        "Aisha Hinds Delves into Hen’s Emotional Journey on ‘9-1-1’",
        "6 Hidden Gems: TV Shows Deserving More Recognition",
        "The Golden Bachelor’s Gerry Turner and Theresa Nist: The Untangling of a Marriage",
        "Avantika’s ‘Rapunzel’ Role Sparks Controversy: A Perspective",
        "Why Heroes Deserves a Revival: A Retrospective",
        "Liza Lapira: Tracing Her Path to Stardom",
        "Checking In on the Cast of Better Call Saul: Where Are They Now?",
        "HBO’s ‘Euphoria’ Season 3 Production Delayed Amid Cast Ventures",
        "7 Big Screen Stars Who Made Stops on General Hospital",
        "Ranking Every Robert De Niro Mobster Role",
        "Anthony Gonzalez: Inside the Life of the Award-Winning Coco Actor",
        "Oscar Nominee Matt Ogens Presents ‘Madu’ at AFI Silver Theatre Prior to Disney+ Debut",
        "Netflix’s ‘Vikings: Valhalla’ Captivates Audiences with Epic Tale",
        "Exploring Awkwafina’s Standout Voice Performances in Film",
        "Meet the Cast of Palm Royale: Apple TV+’s Period Drama",
        "GTA 6: Release Timeline and Teaser Tease New Adventures",
        "Speculations Surrounding Far Cry 7’s Arrival",
        "Legal Woes for Palworld: Lawsuits Looming?",
        "Christian Bale’s Transformation for Maggie Gyllenhaal’s ‘The Bride’",
        "‘Shogun’ Creators Detail Authentic Recreation of Feudal Japan, Tease Season 2",
        "Lauren and Eric Reflect on Sheila’s Complex Past on Bold & Beautiful",
        "Warner Bros. Reveals Plans for ‘Matrix 5’ with Fresh Directorial Vision",
        "Tokyo Vice Creator Teases Season 2 Climax, Hints at Season 3",
        "Stephen Colbert Delivers Emotional Tribute to Late Staffer on ‘Late Show’",
        "The Circle Season 6 Premiere Date and AI Twist on Netflix",
        "Rebel Wilson Accuses Sacha Baron Cohen of Humiliating Her in ‘The Brothers Grimsby’",
        "Craig Conover Shares Optimism About His Long-Distance Relationship With Paige DeSorbo",
        "Will Leo Reveal Jude’s True Parentage to Nicole on Days of Our Lives?",
        "Paramount Confirms Development of Top Gun 3",
        "Stream 7 New Titles on Netflix, Disney Plus, Prime Video, and More This Week",
        "Are We Getting Ted Lasso Season 4?",
        "7 Celebs Who Avoided Jail Time for Major Offenses",
        "Robbie Amell: Meet the ‘Upload’ Star and Sci-Fi Actor",
        "Joel Edgerton: A Journey Through His Television Roles",
        "Is Scream 7 Still in the Works?",
        "John Krasinski: A Journey Through His Directorial Career",
        "What Lies Ahead for the Cars Franchise?",
        "Modern Family: The Making of a Comedy Sensation",
        "6 Facts To Know About Amy Price-Francis",
        "Remembering Susan Flannery: The Legacy of a Soap Opera Icon",
        "Is There Hope for Shrek 5?",
        "Where to Stream Top Boy: Summerhouse Season 5",
        "Gillian Anderson's Views on an X Files Revival",
        "Days of Our Lives Mourns the Loss of Bill Hayes",
        "Remembering General Hospital Alum Robyn Bernard",
        "Remembering O.J. Simpson: The Life of a Former Football Star",
        "10 Celebs Still Without a Star on the Hollywood Walk of Fame",
        "Unveiling Phyllis Smith: The Voice of Sadness From Inside Out",
        "Thomas Mann: Exploring His Career in Film",
        "Remembering All My Children Star Alec Musser",
        "Are We Getting Diablo 5 Soon?",
        "Exploring the Legacy of Lorenzo Lamas",
        "The Journey of C. Thomas Howell: The Outsiders Star",
        "Indiana Jones and the Financial Setback",
        "Melissa Gorga Speaks Out on ‘RHONJ’ Photo Incident",
        "David Cronenberg’s Latest Film Sets Record for Length",
        "Godzilla: A 70-Year Reign as Cinema’s Iconic Monster",
        "General Hospital Teasers: April 8 to April 12, 2024",
        "Ty Pennington: From Reality TV to Design Guru",
        "John Malkovich’s Biggest Box Office Hits",
        "Sarah Beeny: Redefining Home Renovation",
        "Are We Getting a White Collar Comeback?",
        "Breaking Down the Cast of Abigail: The Horror Flick",
        "Amazon’s Fallout Series: Insights into Season 2",
        "The Fate of Red Dead Redemption 3",
        "Far Cry 7: What Fans Need to Know",
        "Rudy Mancuso: Familiar Faces in ‘Música’",
        "Camila Mendes: A Career Retrospective",
        "Starfield: Coming to PS5?",
        "Final Fantasy 16: Expanding to Other Platforms?",
        "Palworld: Bridging Platforms?",
        "Deciphering Sheila Carter’s Bold & Beautiful Disappearance",
        "NCIS Franchise Reaches Milestone with 1000th Episode",
        "Exclusive Friends Script Auctioned for Charity",
        "Remembering Larry David’s ‘Curb Your Enthusiasm’",
        "Anna Devane’s Investigative Journey on General Hospital",
        "Andrew Scott’s Performance in ‘Ripley’",
        "Exploring Walton Goggins’ Roles in Prime Video’s Fallout Series",
        "Vanna White Joins Ryan Seacrest on Talent Shows",
        "The Young and the Restless: April 8-12 Drama Preview",
        "3 Body Problem: A Guide to the Cast and Characters",
        "Bridgerton Season 3: What’s in Store?",
        "Henry Cavill’s Next Move After The Ministry of Ungentlemanly Warfare",
        "Natalie Portman: Beyond Star Wars",
        "The Truth Behind Eric Cartman’s South Park Father",
        "Matt Damon’s Journey with ‘The Talented Mr. Ripley’",
        "Paige Davis’ Net Worth: How Much Does She Earn?",
        "Married at First Sight: Inside Jono McCullough and Ellie Dix’s Relationship",
        "Kristen Wiig’s Aunt Linda Roasts Barbie on SNL’s Weekend Update",
        "Larry David Faces Trial in Curb Your Enthusiasm Finale",
        "Kristen Wiig’s Most Memorable SNL Sketches"
      ID = 1:100
    # Display the data
    # Titles text - TITLES
    title_tokens = extract %>% as.tibble() %>%
      # lowercase
      mutate(title = tolower(title)) %>%
      # tokenize
      unnest_tokens(word, title) %>%
      #remove punct
      mutate(word = str_replace_all(word, "[[:punct:]]", "")) %>%
      # remove numbers 
      filter(!grepl("\\d+", word)) %>%
      # remove stop words
      anti_join(stop_words) %>%
      # stemming
      mutate(word = SnowballC::wordStem(word, language = 'porter'))
    words = title_tokens %>%
      group_by(word) %>%
      summarise(count = n()) %>%
      arrange(desc(count)) %>%
      filter(count!=1) %>%
      dplyr::select(word) %>%
      unlist() %>%
    title_tokens = title_tokens %>% unique() # remove duplicate words. "season, late, "april"
    encoded_title_tokens = title_tokens # %>% filter(word %in% words)
    dummy_matrix <- predict(dummyVars("~ word", data = encoded_title_tokens, sep = "_"), newdata = encoded_title_tokens)
    dummy_matrix <- cbind(id = encoded_title_tokens$ID, as.data.frame(dummy_matrix))
    colnames(dummy_matrix) <- gsub("word_", "", colnames(dummy_matrix))
    colnames(dummy_matrix) <- gsub("word", "", colnames(dummy_matrix))
    encoded_title_tokens = dummy_matrix %>%
      as.data.frame() %>%
      group_by(id) %>%
      summarise(across(everything(), sum)) %>%
    # Jacc dist
    jaccard_matrix_articles = as.tibble(1- prabclus::jaccard(encoded_title_tokens %>%
                             t()  %>%
    umap_jacc = umap::umap(jaccard_matrix_articles,
                           n_components = 3,
                           metric = "euclidean",
                           n_neighbors = 15,
                           min_dist = 0.001, 
                           n_epochs = 200)
    t <- list(
      family = "sans serif",
      size = 10,
      color = plotly::toRGB("grey20"))
    umap_jacc$layout %>% as.tibble() %>%plotly::plot_ly(x = ~V1, y = ~V2, z = ~V3,
                                                    text = extract[encoded_title_tokens$id,]$ID,
                                                        mode = 'markers',
                                                        hoverinfo = 'text') %>%
      plotly::add_text(textfont = t, textposition = "top") %>%
      plotly::add_markers(size = 4) %>%
      plotly::layout(scene = list(xaxis = list(title = "UMAP component 1"),
                                  yaxis = list(title = "UMAP component 2"),
                                  zaxis = list(title = "UMAP component 3")),
                     showlegend = FALSE)
    # v clust 1 
    extract %>% filter(ID %in% c(56,2,18,93,42,62,59,55)) %>% kableExtra::kbl(caption = '<center>Group1</center>', align = 'l') %>%kableExtra::kable_classic() %>% kableExtra::kable_styling()
    # v clust 2
    extract %>% filter(ID %in% c(17,51,3,40,34,91,32,29,73,25)) %>% kableExtra::kbl(caption = '<center>Group2</center>', align = 'l') %>%kableExtra::kable_classic() %>% kableExtra::kable_styling()
    umap_jacc = umap::umap(jaccard_matrix_articles,
                           n_components = 3,
                           input= "dist",
                           n_neighbors = 15,
                           min_dist = 0.001, 
                           n_epochs = 200)
    # Define colors for the three groups
    red_group <- c(56, 2, 18, 93, 42, 62, 59, 55)
    green_group <- c(17, 51, 3, 40, 34, 91, 32, 29, 73, 25)
    # Convert umap_jacc$layout to tibble and add ID column
umap_tibble <- umap_jacc$layout %>%
      as_tibble() %>%
      mutate(ID = 1:nrow(.))
    # Create color column based on IDs
    umap_tibble <- umap_tibble %>%
      mutate(color = case_when(
        ID %in% red_group ~ "red",
        ID %in% green_group ~ "green",
        TRUE ~ "blue"
      )) %>%
      mutate(color = factor(color))
    # Plotly plot
    plot_ly(umap_tibble, x = ~V1, y = ~V2, z = ~V3,
            text = ~ID,  # Display ID as text
            mode = 'markers',
            hoverinfo = 'text') %>%
      add_markers(marker = list(color = ~color), size = 4, showlegend = F) %>%
      add_text(textfont = t, textposition = "top") %>%
      layout(scene = list(xaxis = list(title = "UMAP component 1"),
                          yaxis = list(title = "UMAP component 2"),
                          zaxis = list(title = "UMAP component 3")),
             showlegend = TRUE)

jaccard -> euclidean
jaccard -> euclidean
jaccard -> euclidean visible groups
jaccard -> euclidean groups
jaccard-> euclidean table groups
enter image description here
jaccard as input intput = 'dist'
green and red points are respective groups1 and 2 from jaccard -> euclidean enter image description here



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.