library(tidyverse)
library(rvest)Being a Millennial gamer, I have a fairly well curated (if I do say so myself) Nintendo DS and 3DS catalog. I’ve been looking to get rid of some games I’ve already beaten. Anyone who has sold things on marketplace knows how annoying it can be. I’ve found that if you collect some price data, and find some basic statistics, it makes showing potential buyers that you’ve fairly priced things easier. I get it, everyone wants to save a buck and get a good deal on used games.
I’m looking to sell:
Pokemon SoulSilver
Pokemon Black
Pokemon Platinum
Chrono Trigger
First, let’s load some libraries!
Price Charting
Let’s load in some data from price charting.
url_chrono_trigger <- "https://www.pricecharting.com/game/nintendo-ds/chrono-trigger"
url_pokemon_black <- "https://www.pricecharting.com/game/nintendo-ds/pokemon-black"
url_pokemon_platinum <- "https://www.pricecharting.com/game/nintendo-ds/pokemon-platinum#completed-auctions-cib"
url_pokemon_soulsilver <- "https://www.pricecharting.com/game/nintendo-ds/pokemon-soulsilver-version-pokewalker#completed-auctions-graded"
scrape_data <- function(url) {
page <- read_html(url)
sales_rows <- page |>
html_elements(xpath = "//tr[.//*[contains(concat(' ', normalize-space(@class), ' '), ' date ')]]")
sales <- sales_rows |>
map_dfr(\(row) {
tibble(
date = row |>
html_element(".date") |>
html_text2(),
title = row |>
html_element(".title") |>
html_text2(),
price = row |>
html_element(".numeric .js-price, .numeric") |>
html_text2()
)
}) |>
mutate(
price = parse_number(price)
)
sales <- sales |>
filter(!is.na(price))
return(sales)
}
df_chrono_trigger <- scrape_data(url_chrono_trigger)
df_pokemon_black <- scrape_data(url_pokemon_black)
df_pokemon_platinum <- scrape_data(url_pokemon_platinum)
df_pokemon_soulsilver <- scrape_data(url_pokemon_soulsilver)Cool, now that I have this data I can do a little clean up. Since all of the copies I have are “complete in box” I need to filter out sales that aren’t in the same category.
clean_filter <- function(sales_data) {
output_data <- sales_data |>
filter(
str_detect(
str_to_lower(title),
"cib|complete in box|poster|pokewalker"
)
)
return(output_data)
}
df_cleaned_chrono_trigger <- clean_filter(df_chrono_trigger)
df_cleaned_pokemon_black <- clean_filter(df_pokemon_black)
df_cleaned_pokemon_platinum <- clean_filter(df_pokemon_platinum)
df_cleaned_pokemon_soulsilver <- clean_filter(df_pokemon_soulsilver)Last step here is just to find some basic statistics about the prices so I can make sure to offer a fair price. Median is best to use here since it will trim out the high graded values.
tibble(
game = c(
"Chrono Trigger",
"Pokemon Black",
"Pokemon Platinum",
"Pokemon SoulSilver"
),
median_price = c(
median(df_cleaned_chrono_trigger$price, na.rm = TRUE),
median(df_cleaned_pokemon_black$price, na.rm = TRUE),
median(df_cleaned_pokemon_platinum$price, na.rm = TRUE),
median(df_cleaned_pokemon_soulsilver$price, na.rm = TRUE)
)
)# A tibble: 4 × 2
game median_price
<chr> <dbl>
1 Chrono Trigger 127.
2 Pokemon Black 120.
3 Pokemon Platinum 225
4 Pokemon SoulSilver 382.
I’d love to scrape ebay for prices, but I need to sign up for their api