This report explores patterns within reported UFO sightings. The current analysis focuses on whether the time of day a UFO sighting occurs is associated with the duration of the sighting:
Is the time of day a UFO sighting occurs associated with the duration of the the sighting?
UFO sighting duration is associated with the time of day when the sighting occurs.
The UFO sightings dataset is stored as a CSV file within the project’s data folder. The following code loads the dataset into R for analysis.
ufo <- read.csv("data/ufo_sightings.csv")
How many rows and columns dose this data set contain?
dim(ufo)
## [1] 80332 11
What are the column labels?
names(ufo)
## [1] "datetime" "city" "state"
## [4] "country" "shape" "duration..seconds."
## [7] "duration..hours.min." "comments" "date.posted"
## [10] "latitude" "longitude"
Look at the first 10 rows.
head(ufo, 10)
## datetime city state country shape
## 1 1949-10-10 20:30:00 san marcos tx us cylinder
## 2 1949-10-10 21:00:00 lackland afb tx light
## 3 1955-10-10 17:00:00 chester (uk/england) gb circle
## 4 1956-10-10 21:00:00 edna tx us circle
## 5 1960-10-10 20:00:00 kaneohe hi us light
## 6 1961-10-10 19:00:00 bristol tn us sphere
## 7 1965-10-10 21:00:00 penarth (uk/wales) gb circle
## 8 1965-10-10 23:45:00 norwalk ct us disk
## 9 1966-10-10 20:00:00 pell city al us disk
## 10 1966-10-10 21:00:00 live oak fl us disk
## duration..seconds. duration..hours.min.
## 1 2700 45 minutes
## 2 7200 1-2 hrs
## 3 20 20 seconds
## 4 20 1/2 hour
## 5 900 15 minutes
## 6 300 5 minutes
## 7 180 about 3 mins
## 8 1200 20 minutes
## 9 180 3 minutes
## 10 120 several minutes
## comments
## 1 This event took place in early fall around 1949-50. It occurred after a Boy Scout meeting in the Baptist Church. The Baptist Church sit
## 2 1949 Lackland AFB, TX. Lights racing across the sky & making 90 degree turns on a dime.
## 3 Green/Orange circular disc over Chester, England
## 4 My older brother and twin sister were leaving the only Edna theater at about 9 PM,...we had our bikes and I took a different route home
## 5 AS a Marine 1st Lt. flying an FJ4B fighter/attack aircraft on a solo night exercise, I was at 50ꯠ' in a "clean" aircraft (no ordinan
## 6 My father is now 89 my brother 52 the girl with us now 51 myself 49 and the other fellow which worked with my father if he's still livi
## 7 penarth uk circle 3mins stayed 30ft above me for 3 mins slowly moved of and then with the blink of the eye the speed was unreal
## 8 A bright orange color changing to reddish color disk/saucer was observed hovering above power transmission lines.
## 9 Strobe Lighted disk shape object observed close, at low speeds, and low altitude in Oct 1966 in Pell City Alabama
## 10 Saucer zaps energy from powerline as my pregnant mother receives mental signals not to pass info
## date.posted latitude longitude
## 1 2004-04-27 29.8830556 -97.941111
## 2 2005-12-16 29.38421 -98.581082
## 3 2008-01-21 53.2 -2.916667
## 4 2004-01-17 28.9783333 -96.645833
## 5 2004-01-22 21.4180556 -157.803611
## 6 2007-04-27 36.595 -82.188889
## 7 2006-02-14 51.434722 -3.180000
## 8 1999-10-02 41.1175 -73.408333
## 9 2009-03-19 33.5861111 -86.286111
## 10 2005-05-11 30.2947222 -82.984167
from the head we can see that there are some missing values in the state and country. It dose not affect our current target, but it is worth noting.
What are the variables?
str(ufo)
## 'data.frame': 80332 obs. of 11 variables:
## $ datetime : chr "1949-10-10 20:30:00" "1949-10-10 21:00:00" "1955-10-10 17:00:00" "1956-10-10 21:00:00" ...
## $ city : chr "san marcos" "lackland afb" "chester (uk/england)" "edna" ...
## $ state : chr "tx" "tx" "" "tx" ...
## $ country : chr "us" "" "gb" "us" ...
## $ shape : chr "cylinder" "light" "circle" "circle" ...
## $ duration..seconds. : chr "2700" "7200" "20" "20" ...
## $ duration..hours.min.: chr "45 minutes" "1-2 hrs" "20 seconds" "1/2 hour" ...
## $ comments : chr "This event took place in early fall around 1949-50. It occurred after a Boy Scout meeting in the Baptist Church"| __truncated__ "1949 Lackland AFB, TX. Lights racing across the sky & making 90 degree turns on a dime." "Green/Orange circular disc over Chester, England" "My older brother and twin sister were leaving the only Edna theater at about 9 PM,...we had our bikes and I "| __truncated__ ...
## $ date.posted : chr "2004-04-27" "2005-12-16" "2008-01-21" "2004-01-17" ...
## $ latitude : chr "29.8830556" "29.38421" "53.2" "28.9783333" ...
## $ longitude : num -97.94 -98.58 -2.92 -96.65 -157.8 ...
From this probe we find the columns that we wish to use mathematical analysis on are Chr data types and will need to be changed before they can be useful.
To make sure the original data is perverse before changing the original structure we will make a copy. This will prevent any of the orginal infomation from getting lost. Did the duration..seconds. column become a char because some values have 30 sec in a few records? If so would the conversion delete those rows.
I do not know so we will error on the side of safe and create a copy. Therefore
orginal database -> ufo cleaned database -> ufo_clean
ufo_clean <- ufo
Here we will start with converting the duration_seconds to numeric
ufo_clean$duration_seconds <- as.numeric(ufo_clean$duration..seconds.)
## Warning: NAs introduced by coercion
In doing this We see the Warning message: NAs introduced by coercion this means some of the data has been changed into NA’s. let’s see how many were affected.
sum(is.na(ufo_clean$duration_seconds))
## [1] 3
We see 3 How many of the original data had NA’s?
sum(is.na(ufo$duration..seconds.))
## [1] 0
Although I no do think that is enough information to be worried about, I want to see what is causing this issue.
ufo_clean$duration..seconds.[is.na(ufo_clean$duration_seconds) & !is.na(ufo_clean$duration..seconds.)]
## [1] "2`" "8`" "0.5`"
It looks like we are very lucky were the same typo appears for each. Here we Will get rid of the ` mark
ufo_clean$duration_seconds <- as.numeric(
gsub("`", "", ufo_clean$duration..seconds.))
Checking to see if it worked
sum(is.na(ufo_clean$duration_seconds))
## [1] 0
Great! it worked let’s peek at what the data is telling us about the duration.
summary(ufo_clean$duration_seconds)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 30 180 9017 600 97836000
There are a few things that are worth thinking about when we look at the summary of time. + How is there a duration of 0 seconds + How is the max time of 97,836,000 seconds / 3.1 years + The median is 180 but the mean is 9,017 (is that skewed by the max?) + 75% of the sightings are less than 600 seconds/ 10 minutes
It is highly likely that this data will not have a normal distribution given that the mean and median are a magnitude of order different from each other. This could mean that the traditional t-test is not the best option.
datetime data conversion We just completed the data conversion for the duration in seconds now we need to begin with the date time. Converting it to a numeric I would like to also separate out all of the information in this one column. Currently it has a format of date, hour, min, seconds. I will need the hour to determine if it is day or night for this current hypothesis, my next hypothesis will need the year, and the third will need the month.
The plan is to do the following
datetime original information sighting_datetime properly converted R date-time sighting_date date only year 1949 month 10 hour 20 duration_seconds numeric duration —> this is done
For sighting_datetime I found POSIXct to use exatly for this
ufo_clean$sighting_datetime <- as.POSIXct(ufo_clean$datetime, format = "%Y-%m-%d %H:%M:%S")
Check to see if it worked
class(ufo_clean$sighting_datetime)
## [1] "POSIXct" "POSIXt"
Just like for the seconds I did some investigation of the data to see if there were any NA’s that were not there before. This time 4 were found, after further investigation the 4 NA occurred because of daylight savings time. The “easy fix” for this is to tell R to not apply the computer;s Eastern-time daylight-saving rules
ufo_clean$sighting_datetime <- as.POSIXct(
ufo_clean$datetime,
format = "%Y-%m-%d %H:%M:%S",
tz = "UTC"
)
Moving on to create our date, year, month and hour
ufo_clean$sighting_date <- as.Date(ufo_clean$sighting_datetime)
ufo_clean$year <- as.integer(
format(ufo_clean$sighting_datetime, "%Y")
)
ufo_clean$month <- as.integer(
format(ufo_clean$sighting_datetime, "%m")
)
ufo_clean$hour <- as.integer(
format(ufo_clean$sighting_datetime, "%H")
)
Check it to make sure it worked
head(
ufo_clean[
c("datetime", "sighting_date", "year", "month", "hour",
"duration_seconds")
],
10
)
## datetime sighting_date year month hour duration_seconds
## 1 1949-10-10 20:30:00 1949-10-10 1949 10 20 2700
## 2 1949-10-10 21:00:00 1949-10-10 1949 10 21 7200
## 3 1955-10-10 17:00:00 1955-10-10 1955 10 17 20
## 4 1956-10-10 21:00:00 1956-10-10 1956 10 21 20
## 5 1960-10-10 20:00:00 1960-10-10 1960 10 20 900
## 6 1961-10-10 19:00:00 1961-10-10 1961 10 19 300
## 7 1965-10-10 21:00:00 1965-10-10 1965 10 21 180
## 8 1965-10-10 23:45:00 1965-10-10 1965 10 23 1200
## 9 1966-10-10 20:00:00 1966-10-10 1966 10 20 180
## 10 1966-10-10 21:00:00 1966-10-10 1966 10 21 120
Since we have the hours out lets see how many sightings by hour
table(ufo_clean$hour)
##
## 0 1 2 3 4 5 6 7 8 9 10 11 12
## 4802 3210 2357 2004 1529 1591 1224 905 803 958 1166 1144 1368
## 13 14 15 16 17 18 19 20 21 22 23
## 1303 1322 1433 1620 2592 4002 6147 8617 11445 10837 7953
Looking at this let divide this into 4 sections
Overnight 0–5 Morning 6–11 Afternoon 12–17 Evening 18–23
ufo_clean$time_period <- cut(
ufo_clean$hour,
breaks = c(-1, 5, 11, 17, 23),
labels = c("Overnight", "Morning", "Afternoon", "Evening")
)
Let’s look at this in a table form
table(ufo_clean$time_period)
##
## Overnight Morning Afternoon Evening
## 15493 6200 9638 49001
Remember how the mean and median were very different and the max value was much larger than the 3rd quarter/75% of the data? Spoiler alert I looked at the max data’s description. The description stated that it was only a few seconds. Most likely it is a typo, but reading 80k plus descriptions is a bit much, so lets see if math can help.
ggplot(ufo_clean, aes(x = time_period, y = duration_seconds / 60)) +
geom_boxplot() +
labs(
title = "UFO Sighting Duration by Time of Day",
x = "Time of Day",
y = "Duration (Minutes)"
)
I am going to start with grouping the hourly duration using the dplyr library. We should expect to see 24 groups
hourly_duration <- ufo_clean %>% group_by(hour) %>% summarise(median_duration_seconds = median(median(duration_seconds)))
dim(hourly_duration)
## [1] 24 2
Let’s add a row for munitues
hourly_duration <- ufo_clean %>%
group_by(hour) %>%
summarise(median_duration_seconds = median(duration_seconds)
) %>%
mutate(median_duration_minutes = median_duration_seconds / 60)
print(hourly_duration, n = 24)
## # A tibble: 24 × 3
## hour median_duration_seconds median_duration_minutes
## <int> <dbl> <dbl>
## 1 0 180 3
## 2 1 180 3
## 3 2 180 3
## 4 3 180 3
## 5 4 180 3
## 6 5 180 3
## 7 6 180 3
## 8 7 180 3
## 9 8 180 3
## 10 9 180 3
## 11 10 180 3
## 12 11 180 3
## 13 12 180 3
## 14 13 120 2
## 15 14 180 3
## 16 15 180 3
## 17 16 180 3
## 18 17 180 3
## 19 18 180 3
## 20 19 180 3
## 21 20 180 3
## 22 21 180 3
## 23 22 180 3
## 24 23 180 3
I decided to go with the box plot and use a log10 scale because we have observed that there is a large right tail to this dataset that can still be useful.
ggplot(ufo_clean, aes(x = time_period, y = duration_seconds / 60)) +
geom_boxplot() +
scale_y_log10() +
labs(
title = "UFO Sighting Duration by Time of Day",
x = "Time of Day",
y = "Duration (Minutes, Log Scale)"
)
The boxplot shows that the median UFP sighting duration is similar across the four time periods. However, there is some variation in the interquartile ranges (between Q1 and Q3), with overnight sightings showing a wider spread in the middle 50% of reported duration. the distributions are also strongly right-skewed, with many high-duration outliers across the four time periods.
The logarithmic scal is used because the repoted UPF sighting duration spans a very large range. on the y-axis each increase represents an order of magnitude. This allows the more abundent short duration sightingd to remain visible withour being compressed by the small number of extermely long-duration sightings.
duration_summary <- ufo_clean %>%
group_by(time_period) %>%
summarise(
count = n(),
Q1_minutes = quantile(duration_seconds / 60, 0.25),
median_minutes = median(duration_seconds / 60),
Q3_minutes = quantile(duration_seconds / 60, 0.75),
IQR_minutes = IQR(duration_seconds / 60)
)
duration_summary
## # A tibble: 4 × 6
## time_period count Q1_minutes median_minutes Q3_minutes IQR_minutes
## <fct> <int> <dbl> <dbl> <dbl> <dbl>
## 1 Overnight 15493 0.5 3 15 14.5
## 2 Morning 6200 0.5 3 10 9.5
## 3 Afternoon 9638 0.5 3 10 9.5
## 4 Evening 49001 0.5 3 10 9.5
Although the median reported sighting duration is 3 for all four time periods the larger interquartile range(IQR) is seen in the overnight as seen in the previous boxplot.
with that in mind the IQR/variability is easier to see in the chart below. It dose not mean that the sightings are longer, it only means that there is more variability during this time range.
ggplot(duration_summary,
aes(x = time_period, y = IQR_minutes)) +
geom_col() +
labs(
title = "Variation in UFO Sighting Duration by Time of Day",
x = "Time of Day",
y = "Interquartile Range (Minutes)"
)
For question 3 we are asking “Is there a measurable statistical relationship between time of day and sighting duration?”. for this questions we will look deeper into correlation, R^2, p-value, scatterplot and regression line. this section will be a little different because of the large duration times. like with the box plot using the log10 scale so the right tail dose not dominate the data we will use the log10 scale for the regression process as well.
lets look at one of the main differences when interpenetrating the data. Notice how the median is not 3 like we previously calulated or is it?
It is because we are looking at the log10 format the data is based off of log 10. so if you take 10^2.255273 is about 180 seconds which is the 3 minutes. Likewise when you see the -3 that is 0.001 seconds. This is very useful and needed because our values span over orders of magnitude. So we are thinking about the ratios rather than enormous absolute differences.
# Log-transform sighting duration to reduce the effect of extreme right-skew
ufo_clean$log_duration <- log10(ufo_clean$duration_seconds)
summary(ufo_clean$log_duration)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -3.000 1.477 2.255 2.150 2.778 7.990
let’s take a look at the correlation
duration_correlation <- cor.test(
ufo_clean$hour,
ufo_clean$log_duration,
method = "pearson"
)
duration_correlation
##
## Pearson's product-moment correlation
##
## data: ufo_clean$hour and ufo_clean$log_duration
## t = -3.7533, df = 80330, p-value = 0.0001747
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.020154660 -0.006326677
## sample estimates:
## cor
## -0.0132413
First we see that the correlation number is r = -0.01324. with the Pearson’s model it ranges from -1 to 1 where 0 represents no relationship. since we are really close to 0 the negative linear relationship is essentially negligible. Interesting the p value is 0.0001747 where the significance level is 0.05, so this says that the correlation is statistically significant. The negative linear relationship is extremely week. Therefore, the hour of day explains very little of the variation in sighting duration through a simple linear relationship.
(-0.0132413 )^2*100
## [1] 0.0175332
This shows the hour of day explains only 0.018% of the variation in log-transformed UFO sighting duration within this linear model. This meas that the linear model dose not fit, but it dose not yet prove the theory wrong.
##Scatter plot
ggplot(
ufo_clean,
aes(x = hour, y = log_duration)
) +
geom_jitter(
width = 0.2,
height = 0,
alpha = 0.05
) +
geom_smooth(
method = "lm",
se = FALSE
) +
labs(
title = "Relationship Between Time of Day and UFO Sighting Duration",
x = "Hour of Day",
y = "Log10 Sighting Duration (Seconds)"
)
## `geom_smooth()` using formula = 'y ~ x'
The Pearson correlation and simple linear regression were used to examine the relationship between hour of day and log10- transformed UFO sighting duration. The correlation was statistically significant (r = -0.0132, p = 0.0001747), but the magnitude of the relationship was extremely weak. The linear regression produced an R^2 of 0.000175. that indicated that our hour of day explained approximately 0.018% of the variation in the log-transformed sighting duration. The scatterplot supports this result, as the regression line is essentially horizontal and no strong linear pattern is visible.
Therefore, although the relationship is statistically significant, the results provide little evidence of a meaningful linear relationship between hour of day and sighting duration
Here is a histogram using the log10 so the small number of long duration numbers do not over power the average UFO sightings numbers. As we saw earlier the data transformation is more balanced than the original data but it is not perfectly symmetric and the right tail remains. Several peaks are also visible, which may reflect the tendency for reported sighting duration to occur at a common rounded values.
ggplot(ufo_clean, aes(x = log_duration)) +
geom_histogram(bins = 48) +
labs(
title = "Distribution of Log-Transformed UFO Sighting Durations",
x = "Log10 of Sighting Duration (Seconds)",
y = "Number of Sightings"
)
Let’s take a look with more bins
ggplot(ufo_clean, aes(x = log_duration)) +
geom_histogram(bins = 75) +
labs(
title = "Distribution of Log-Transformed UFO Sighting Durations",
x = "Log10 of Sighting Duration (Seconds)",
y = "Number of Sightings"
)
For this section I am going to divide the data into two groups.
ufo_clean$day_night <- ifelse(
ufo_clean$hour >= 6 & ufo_clean$hour < 18,
"Day",
"Night"
)
ufo_clean$day_night <- factor(
ufo_clean$day_night,
levels = c("Day", "Night")
)
table(ufo_clean$day_night)
##
## Day Night
## 15838 64494
Since we already know that the data is right skew we might need to continue with log10 transformations.From the simple count table we can see that about 80% of the sightings are in the nigth group. However we should look at how the data looks in the groups before deciding.
day_night_summary <- ufo_clean %>%
group_by(day_night) %>%
summarise(
count = n(),
median_minutes = median(duration_seconds / 60),
mean_minutes = mean(duration_seconds / 60),
IQR_minutes = IQR(duration_seconds / 60),
mean_log_duration = mean(log_duration),
sd_log_duration = sd(log_duration)
)
day_night_summary
## # A tibble: 2 × 7
## day_night count median_minutes mean_minutes IQR_minutes mean_log_duration
## <fct> <int> <dbl> <dbl> <dbl> <dbl>
## 1 Day 15838 3 158. 9.5 2.12
## 2 Night 64494 3 148. 9.5 2.16
## # ℹ 1 more variable: sd_log_duration <dbl>
ggplot(
ufo_clean,
aes(x = day_night, y = log_duration)
) +
geom_boxplot() +
labs(
title = "Log-Transformed UFO Sighting Duration: Day vs. Night",
x = "Time Period",
y = "Log10 of Sighting Duration (Seconds)"
)
We see that the data is remarkably similar in the typical duration, (again).
*Standard*
** Mean**
Median has the same for both day and night at 3mins. We found this earlier, where the differences between the mean and median highlights how the extreme duration affect the raw data.
*log transformation*
Mean
Log Standard Deviation.
Given this information I will move forward with the Welch two-sample t-test, we are handling unequal group sizes and doesn’t require us to assume the two populations have equal variances.
The null hypothesis is:
\[ H_0: \mu_{Day} = \mu_{Night} \]
The alternative hypothesis is:
\[ H_A: \mu_{Day} \neq \mu_{Night} \]
Running the Test
day_night_ttest <- t.test(
log_duration ~ day_night,
data = ufo_clean
)
day_night_ttest
##
## Welch Two Sample t-test
##
## data: log_duration by day_night
## t = -4.4325, df = 24983, p-value = 9.353e-06
## alternative hypothesis: true difference in means between group Day and group Night is not equal to 0
## 95 percent confidence interval:
## -0.05251195 -0.02031007
## sample estimates:
## mean in group Day mean in group Night
## 2.121021 2.157432
As you can see The Welch t-tesr gave us:
t=-4.4325, and p=9.353x10^-6
Since p<0.05 We reject the null hypotheses that the Day and Night groups have equal mean log-transformed durations. but we also need to look at the size of the difference before knowing what this test is actually telling us.
Mean
Therefore Day-Night = -0.036411, The negative t-statistic, But remember we are using log transformation so we must take a look at
10^0.036411
## [1] 1.087454
This is telling us the geometric-mean duration for Night is approximately 1.087 times the Day value an increase of 8.7%. Again this is not the whole story because the confidence interval of -0.05251195 to -0.02031007 is below zero, it agrees with the p-value: the estimated mean log duration is lower for the day than the night. It dose not cross the zero, so zero difference isn’t supported at the 95% confidence level.
The Null hypothesis of equal mean log-transformed duration is rejected; however, the results do not indicate a large practical difference in sighting duration between the Day and Night periods. A Welch two-sample t-test was used to compare log10-transformed sighting durations between the Day (06:00–17:59) and Night (18:00–05:59) groups. The test found a statistically significant difference between the groups, t = -4.43, p < 0.001. The mean log10 duration was 2.121 for Day sightings and 2.157 for Night sightings. Although the difference was statistically significant, its magnitude was small. The median duration was 3 minutes and the IQR was 9.5 minutes for both groups, indicating that the typical durations and spread of the middle 50% were very similar. Therefore, the large sample size allowed the test to detect a small difference that may have little practical significance.