{"id":20388753,"url":"https://github.com/mkearney/trumptweets","last_synced_at":"2025-09-23T04:56:57.125Z","repository":{"id":124080003,"uuid":"80078384","full_name":"mkearney/trumptweets","owner":"mkearney","description":"Download data on all of Donald Trump's (@realDonaldTrump) tweets","archived":false,"fork":false,"pushed_at":"2018-10-02T04:25:01.000Z","size":39607,"stargazers_count":42,"open_issues_count":2,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T10:55:42.005Z","etag":null,"topics":["dataset","donald-trump","mkearney-dataset","r","r-rtweet","tweets","twitter","twitter-api"],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkearney.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-01-26T02:10:26.000Z","updated_at":"2025-04-11T06:32:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"ddd28671-aa04-4046-b6ca-15f3e557129f","html_url":"https://github.com/mkearney/trumptweets","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mkearney/trumptweets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkearney%2Ftrumptweets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkearney%2Ftrumptweets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkearney%2Ftrumptweets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkearney%2Ftrumptweets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkearney","download_url":"https://codeload.github.com/mkearney/trumptweets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkearney%2Ftrumptweets/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276518810,"owners_count":25656497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-23T02:00:09.130Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dataset","donald-trump","mkearney-dataset","r","r-rtweet","tweets","twitter","twitter-api"],"created_at":"2024-11-15T03:13:10.530Z","updated_at":"2025-09-23T04:56:57.119Z","avatar_url":"https://github.com/mkearney.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\n## Read data\n\n\n```{r}\n## read csv file\n#rdt \u003c- read.csv(\"data/trumptweets-1515775693.tweets.csv\")\nrdt \u003c- readRDS(\"data/trumptweets-1515775693.rds\")\n\n## preview data\nrdt\n```\n\n## Download all of Donald Trump's tweets using R\n\n1. Install and load rtweet. `\n\n```{r, eval=FALSE}\n## install rtweet package\ninstall.packages(\"rtweet\")\n\n## alternatively, install dev version\nif (!\"devtools\" %in% installed.packages()) {\n  install.packages(\"devtools\")\n}\ndevtools::install_github(\"mkearney/rtweet\")\n\n## load rtweet\nlibrary(rtweet)\n```\n\n2. Read in the following 3 functions. You'll use the last\nfunction, `trumptweets()`, to download the data.\n\n```{r, eval=FALSE}\n#' get_trumptwitterarchive\n#'\n#' Returns data from trumptwitterarchive.com.\n#'\n#' @param years Years from which to collect data. Defaults (NULL, TRUE, or \"all\")\n#'   to 2008-current year.\n#' @return Returns data frame (tbl) of status IDs with \"data\" attribute consisting of\n#'   list of data by year.\n#' @importFrom jsonlite fromJSON\n#' @importFrom tibble as_tibble\n#' @examples\n#' \\dontrun{\n#' ## get data\n#' tta \u003c- get_trumptwitterarchive()\n#'\n#' @export\nget_trumptwitterarchive \u003c- function(years = NULL) {\n  ## default to years 2008 through current\n  if (is.null(years) || isTRUE(years) || identical(tolower(years), \"all\")) {\n    years \u003c- seq(2009, as.integer(format(Sys.Date(), \"%Y\")))\n  }\n  stopifnot(is.numeric(years))\n  ## get data for each year\n  tta \u003c- lapply(years, trumptwitterarchive_)\n  ## make status IDs data frame with tta as attribute\n  ids \u003c- lapply(tta, \"[[\", \"id_str\")\n  ids \u003c- tibble::as_tibble(\n    list(status_id = unlist(ids)),\n    validate = FALSE\n  )\n  ## list of data (element = year)\n  attr(ids, \"data\") \u003c- tta\n  attr(ids, \"years\") \u003c- years\n  ids\n}\n\n#' trumptwitterarchive_data\n#'\n#' Extracts full trumptwitterarchive data\n#'\n#' @param data Data frame returned by \\code{\\link{get_trumptwitterarchive}} with\n#'   \"data\" attribute.\n#' @param years Optional integer used to subset data to return only certain years.\n#'   Defaults to NULL, which means all data is returned.\n#' @return List of full data from trumptwitterarchive.com.\n#' @export\ntrumptwitterarchive_data \u003c- function(data, years = NULL) {\n  if (!\"data\" %in% names(attributes(data))) {\n    stop(\"Archive data not found\", call. = FALSE)\n  }\n  tta \u003c- attr(data, \"data\")\n  ## by default, return tta data\n  if (is.null(years)) {\n    return(tta)\n  }\n  ## if years to subset are provided\n  data_years \u003c- attr(data, \"years\")\n  ## if no years attr or if years length differs return w/ warning\n  if (is.null(data_years) || length(data_years) != length(years)) {\n    warning(\n      \"Length of years attribute differs from length of data. Returning all extracted data\",\n      call. = FALSE\n    )\n  } else {\n    tta \u003c- tta[data_years %in% years]\n  }\n  tta\n}\n\n\n\n#' trumptwitterarchive_\n#'\n#' Internal function used to retrieve trumptwitterarchive data\n#'\n#' @param year Integer, specifying year of data to return.\n#' @param fromJSON Logical, indicating whether to convert repsonse object to\n#'   nested list object.\n#' @return Response object from trumptwitterarchive request converted (by default)\n#'   to R-friendly list object.\n#' @importFrom httr content GET\n#' @importFrom jsonlite fromJSON\n#' @noRd\n#' @keywords internal\ntrumptwitterarchive_ \u003c- function(year, fromJSON = TRUE) {\n  ## build and send request\n  url \u003c- paste0(\n    \"http://trumptwitterarchive.com/\",\n    \"data/realdonaldtrump/\",\n    year,\n    \".json\"\n  )\n  ## response object\n  r \u003c- httr::GET(url)\n  ## check html status\n  httr::warn_for_status(r)\n  ## if fromJSON then convert to list otherwise return response object\n  if (fromJSON) {\n    r \u003c- httr::content(r, \"text\")\n    ## if html return empty data frame\n    if (grepl(\"^\\\\\u003c\\\\!DOCTYPE\", r)) {\n      r \u003c- data.frame()\n    } else {\n      r \u003c- jsonlite::fromJSON(r)\n    }\n  }\n  r\n}\n\n## function to download status ids\ntrumpids \u003c- function(trumptwitterarchive = TRUE) {\n    ## scrape from trumptwitterarchive.com\n    if (trumptwitterarchive) {\n        ids \u003c- c(2009:2017) %\u003e%\n            lapply(.trumpids) %\u003e%\n            unlist(use.names = FALSE)\n    } else {\n        ## or from my github page (note: this one is unlikely to\n        ## be updated as frequently as trumptwitterarchive)\n        ids \u003c- paste0(\n            \"https://github.com/mkearney/trumptweets/blob/\",\n            \"master/data/realdonaldtrump-ids-2009-2017.csv\") %\u003e%\n            read.csv(stringsAsFactors = FALSE) %\u003e%\n            unlist(use.names = FALSE)\n    }\n    ## return ids\n    ids\n}\n\n## function to download twitter data\ntrumptweets \u003c- function() {\n    ## get archive of status ids\n    ids \u003c- trumpids()\n    ## get newest trump tweets (set to 1000 to be safe)\n    rt1 \u003c- get_timeline(\n        \"realdonaldtrump\", n = 1000,\n        since_id = ids[length(ids)])\n    ## download archive\n    message(\"    Downloading \", length(ids), \" tweets...\")\n    rt2 \u003c- lookup_statuses(ids[1:16000])\n    message(\"    You're halfway there...\")\n    rt3 \u003c- lookup_statuses(ids[16001:(length(ids))])\n    message(\"    Huzzah!!!\")\n    ## combine data into list\n    rt \u003c- list(rt1, rt2, rt3)\n    ## collapse into data frame (or salvage list if error)\n    tryCatch(do.call(\"rbind\", rt),\n             error = function(e) return(rt))\n}\n```\n\n3. Download all of Trump's tweets.\n\n```{r, eval=FALSE}\n## run function to download Trump's twitter archive\ndjt \u003c- trumptweets()\n```\n\n4. Save the data file.\n\n```{r, eval=FALSE}\n## To save as an excel file:\ninstall.packages(\"openxlsx\")\nopenxlsx::write.xlsx(djt, \"realdonaltrump-fullarchive.xlsx\")\n\n## To save as csv file\nwrite.csv(djt, \"realdonaltrump-fullarchive.csv\",\n          row.names = FALSE)\n\n## To preserve meta information and save as csv file\ninstall.packages(\"readr\")\nreadr::write_csv(djt, \"realdonaltrump-fullarchive.csv\")\n```\n\n## Inspecting the data\n\n```{r, eval=FALSE}\n## preview data\nhead(djt)\n\n## check 100 most popular hashtags\ndjt$hashtags %\u003e%\n    strsplit(\" \") %\u003e%\n    unlist(use.names = FALSE) %\u003e%\n    tolower %\u003e%\n    table() %\u003e%\n    sort(decreasing = TRUE) %\u003e%\n    head(100)\n\n## check 100 most popular mentions\ndjt$mentions_screen_name %\u003e%\n    strsplit(\" \") %\u003e%\n    unlist(use.names = FALSE) %\u003e%\n    tolower %\u003e%\n    table() %\u003e%\n    sort(decreasing = TRUE) %\u003e%\n    head(100)\n\n## check text of 50 most recent tweets\ndjt$text[1:50]\n```\n\n## Plotting the data\n\n```{r, eval = FALSE}\n## use the built in rtweet function\nts_plot(p, theme = \"nerdy\")\n\n## plot four groups of hashtags\np \u003c- ts_filter(djt, \"2 days\", txt = \"hashtags\",\n               filter = c(\"makeamericagreatagain|maga\",\n                          \"trump\",\n                          \"debate\",\n                          \"draintheswamp|americafirst\"),\n               key = c(\"MakeAmericaGreatAgain\",\n                       \"Trump\",\n                       \"Debates\",\n                       \"DrainTheSwamp/AmericaFirst\"))\n\n## you can continue plotting with rtweet functions but\n## the current version (0.4.0) prints incorrect labels for\n## the x-axis for multi-year plots.\nts_plot(p, theme = \"spacegray\")\n\n## ggplot2 doesn't have that problem and is more robust and\n## flexible anyway\n## install and load ggplot2\ninstall.packages(\"ggplot2\")\nlibrary(ggplot2)\n\n## uncomment following line and final line to save image\n## png(\"trumptweets.png\", 7, 5, \"in\", res = 127.5)\np %\u003e%\n    ggplot(aes(x = time, y = freq, color = filter)) +\n    theme_bw() +\n    geom_line() +\n    facet_wrap( ~ filter, ncol = 2) +\n    labs(x = \"\", y = \"\",\n         title = \"Hashtags used by Donald Trump\",\n         subtitle = \"Used entire archive of @realDonaldTrumpTweets\") +\n    theme(legend.position = \"none\",\n          text = element_text(size = 12,\n                              family = \"Avenir Next Condensed\"),\n          plot.title = element_text(\n              family = \"Avenir Next Condensed Medium\", size = 20))\n## dev.off()\n\n## image I created using this code displayed below\n\n## note: if Avenir Next Condensed will only work if currently\n## installed on your machine. If that's the case, then either\n## delete the family arguments or replace Avenir with the font\n## of your choosing.\n```\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"trumptweets.png\" alt=\"tweets\"\u003e\n\u003c/p\u003e\n\n\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"trumpsentiment.png\" alt=\"sentiment\"\u003e\n\u003c/p\u003e\n\n\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"rtfvs.png\" alt=\"rt\"\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkearney%2Ftrumptweets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkearney%2Ftrumptweets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkearney%2Ftrumptweets/lists"}