This report analyzes data on ship-based imports into the United States, highlighting the extraordinary portion of imports that are delivered via the Ports of Los Angeles and Long Beach. While technically separate ports with distinct management, the facilities are direct neighbors and operations flow between the facilities. These two ports, alongside the Port of New York, consistently compete for the title of largest importer. Combined, these two ports represent over a third of imports into the United States.
The following image indicates just how closely located the two
facilities (the Ports of Long Beach and LA) are.
container.ports.2000.2017 <- read.csv("/Users/codyr/Downloads/container-ports-2000-2017.csv")
The dataset is comprised of 63 US Ports, and their annual imports, in metric tons, from 2000 to 2017, as well as information such as the location (coast) of the port. The data was downloaded from Kaggle. The original source of the data comes from the U.S. Department of Transportation Maritime Administration, showing U.S. Waterborne Foreign Container Trade by US customs ports 2000-2017.
The following charts display information regarding imports into the United States.
#changing format so it is in 'long' format
df <- container.ports.2000.2017 %>%
pivot_longer(cols = starts_with("X"),
names_to = "Year",
names_prefix = "X",
values_to = "Value")
df$Value <- as.integer(gsub(",", "", df$Value))
#renaming "Value" column to "Metric Tons"
colnames(df)[4] <- "Metric_Tons"
#Summarizing the data by port (totals)
port_totals <- df %>%
group_by(U.S..Custom.Ports) %>%
summarise(Total = sum(Metric_Tons)) %>%
arrange(desc(Total)) %>%
slice_head(n = 10)
Combined import totals over the entire 17 year period show that Los Angeles is dominating its competing ports - larger than New York by over 50 million metric tons. Following the Port of Long Beach, import totals drop off to less than a third of Los Angeles’ total.
#creating plot - total imports by port (2000 - 2017)
ggplot(port_totals, aes(x = reorder(U.S..Custom.Ports, -Total), y = Total)) +
geom_bar(stat = 'identity', fill = 'skyblue') +
geom_text(aes(label = paste0(scales::comma(Total / 1e6), "M")), vjust = -0.5, colour = "black", size = 3) +
labs(x = "Port", y = "Imports (Metric Tons)", title = "Total Imports by US Port - Top 10 (2000 - 2017)") +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
scale_y_continuous(labels = function(x) paste0(scales::comma(x / 1e6), "M"))
Port totals fluctuate considerably. Despite Los Angeles’ general domination, as of 2017, New York had the year with the highest volume of imports (27 million metric tons in 2017). This chart further emphasizes the separate league that Los Angeles, Long Beach, and New York encompass.
#first, get the top ports:
top_ports <- port_totals %>%
top_n(10, Total) %>%
pull(U.S..Custom.Ports)
#filter original df to only have these top ports
top_ports_df <- df %>%
filter(U.S..Custom.Ports %in% top_ports)
#turning into factor
top_ports_df$Year <- as.factor(top_ports_df$Year)
#hilo points
hi_point <- top_ports_df %>%
slice_max(order_by = Metric_Tons, n = 1)
#plotting LINE
ggplot(top_ports_df, aes(x = Year, y = Metric_Tons, group = U.S..Custom.Ports)) +
geom_line(aes(color = U.S..Custom.Ports), size = 1) +
geom_point(aes(color = U.S..Custom.Ports), size = 2) +
labs(title = "Imports by Port and by Year (Top 10 ports by volume)", x = "Year", y = "Imports (Metric Tons)") +
theme_light() +
theme(plot.title = element_text(hjust = 0.5),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
scale_y_continuous(labels = function(x) paste0 (scales::comma(x / 1e6), "M")) +
geom_label_repel(
data = hi_point,
aes(label = paste(U.S..Custom.Ports, ":", scales::comma(Metric_Tons / 1e6), "M", "(", Year, ")")),
size = 3,
nudge_y = 0.05 * max(top_ports_df$Metric_Tons),
nudge_x = 0.05,
segment.color = "grey50"
)
Highlighting and combining just Los Angeles and Long Beach, we can see the considerable percentage of US imports that these facilities unload.
donuts_data <- df %>%
mutate(U.S..Custom.Ports = ifelse(U.S..Custom.Ports %in% c("Long Beach, CA", "Los Angeles, CA"), U.S..Custom.Ports, "Other Ports"))
donuts_data <- donuts_data %>%
group_by(Year, U.S..Custom.Ports) %>%
summarise(Metric_Tons = sum(Metric_Tons),
.groups = 'drop')
donuts_data_final <- donuts_data %>%
group_by(Year, U.S..Custom.Ports) %>%
summarise(Metric_Tons = sum(Metric_Tons), .groups = 'drop')
donuts_data_final <- donuts_data_final %>%
group_by(Year) %>%
mutate(total_metric_tons = sum(Metric_Tons),
percent_of_total = (Metric_Tons / total_metric_tons) * 100) %>%
select(-total_metric_tons)
plot_ly(hole = 0.7) %>%
layout(title = "Annual Imports by Port: 2014-2016") %>%
add_trace(
data = filter(donuts_data_final, Year == 2016),
labels = ~U.S..Custom.Ports,
values = ~Metric_Tons,
type = "pie",
textposition = "inside",
hovertemplate = "Year: 2016<br>Port: %{label}<br>Percent: %{percent}<br>Metric Tons: %{value}<extra></extra>") %>%
add_trace(
data = filter(donuts_data_final, Year == 2015),
labels = ~U.S..Custom.Ports,
values = ~Metric_Tons,
type = "pie",
textposition = "inside",
hovertemplate = "Year: 2015<br>Port: %{label}<br>Percent: %{percent}<br>Metric Tons: %{value}<extra></extra>",
domain = list(
x = c(0.16,0.84),
y = c(0.16,0.84))) %>%
add_trace(
data = filter(donuts_data_final, Year == 2014),
labels = ~U.S..Custom.Ports,
values = ~Metric_Tons,
type = "pie",
textposition = "inside",
hovertemplate = "Year: 2014<br>Port: %{label}<br>Percent: %{percent}<br>Metric Tons: %{value}<extra></extra>",
domain = list(
x = c(0.27,0.73),
y = c(0.27,0.73)))
In recent years Atlantic Coast imports have surpassed Pacific Coast imports, and continue to grow. While Los Angeles and Long Beach represent huge (and nearly combined) facilities, they do not match the overall import totals of the Atlantic Coast.
df <- df %>%
mutate(Year = as.integer(Year))
heatmap_data <- df %>%
filter(Year >= 2012 & Year <= 2016) %>%
group_by(Year, Coast) %>%
summarise(Total_Metric_Tons = sum(Metric_Tons), .groups = 'drop')
heatmap_data <- heatmap_data %>%
filter(Coast != "" & Coast != "AK" & Coast != "HI" & Coast != "PR" & Coast != "G" & !is.na(Coast))
#creating heatmap
ggplot(heatmap_data, aes(x = Year, y = Coast, fill = Total_Metric_Tons)) +
geom_tile(color = "black") +
geom_text(aes(label = scales::comma(Total_Metric_Tons)), color = "black") +
coord_equal(ratio = 1) +
labs(title = "Heatmap: Imports by Coast and Year",
x = "Year",
y = "Coast",
fill = "Metric Tons",
caption = "Coastal Codes: P = Pacific, A = Atlantic") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5)) +
scale_y_discrete(limits = rev(levels(heatmap_data$Coast))) +
scale_fill_gradient(low = "yellow", high = "darkred") +
guides(fill = guide_colorbar(title = "Metric Tons", reverse = TRUE))
Finally, this graphic identifies the combined totals of the ports of Los Angeles and Long Beach, as opposed to the rest of the ports. This graphic starkly shows the dominance of these two Southern California facilities, though it also shows a dwindling percentage of total imports, going from nearly 35% in 2011 to 30.6% in 2016.
trellis_data <- df %>%
mutate(U.S..Custom.Ports = ifelse(U.S..Custom.Ports %in% c("Los Angeles, CA", "Long Beach, CA"), "Los Angeles + Long Beach", "Other Ports")) %>%
group_by(Year, U.S..Custom.Ports) %>%
summarise(Metric_Tons = sum(Metric_Tons), .groups = 'drop')
color_palette <- c('#ff7f0e','#8c564b')
p <- plot_ly(trellis_data, textposition = "inside") %>%
add_pie(
data = subset(trellis_data, Year == "2011"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2011", domain = list(row = 0, column = 0),
hoverinfo = "label+percent+name", textinfo = "none",
marker = list(colors = color_palette)
) %>%
add_pie(
data = subset(trellis_data, Year == "2012"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2012", domain = list(row = 0, column = 1),
hoverinfo = "label+percent+name", textinfo = "none"
) %>%
add_pie(
data = subset(trellis_data, Year == "2013"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2013", domain = list(row = 1, column = 0),
hoverinfo = "label+percent+name", textinfo = "none"
) %>%
add_pie(
data = subset(trellis_data, Year == "2014"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2014", domain = list(row = 1, column = 1),
hoverinfo = "label+percent+name", textinfo = "none"
) %>%
add_pie(
data = subset(trellis_data, Year == "2015"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2015", domain = list(row = 2, column = 0),
hoverinfo = "label+percent+name", textinfo = "none"
) %>%
add_pie(
data = subset(trellis_data, Year == "2016"),
labels = ~U.S..Custom.Ports, values = ~Metric_Tons,
name = "2016", domain = list(row = 2, column = 1),
hoverinfo = "label+percent+name", textinfo = "none"
) %>%
layout(
title = "Annual Imports by Port: LA + LB (2011-2016)",
grid = list(rows = 3, columns = 2),
showlegend = TRUE,
paper_bgcolor = 'rgba(245,246,249,1)',
annotations = list(
list(text = "2011", x = -0.05, y = 0.9, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16)),
list(text = "2012", x = 0.55, y = 0.9, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16)),
list(text = "2013", x = -0.05, y = 0.6, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16)),
list(text = "2014", x = 0.55, y = 0.6, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16)),
list(text = "2015", x = -0.05, y = 0.3, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16)),
list(text = "2016", x = 0.55, y = 0.3, xref = "paper", yref = "paper", showarrow = FALSE, font = list(size = 16))
))
p
Upon analyzing the dataset, the dominance of the Ports of Los Angeles, Long Beach, and New York quickly becomes apparent. The relative proximity of Los Angeles and Long Beach, along with their total volume, make them an interesting target of analysis. The data also creates some questions. While LA and Long Beach represent nearly a third of US imports, the Atlantic Coast is outpacing growth on the Pacific Coast and has taken the lead as far as total imports. Could LA and Long Beach dominance have to do with relatively fewer West Coast ports? Or a more concentrated population on the Pacific as opposed to the Atlantic Coasts? These questions can be answered with more data anslysis, and subject matter expertise.