In this project, I am going to analyze submissions to Hacker News and compare the number of comments for "Ask HN" and "Show HN" posts. Then I will analyze and determine if posts created at a certian time recieve more comments on average. Ultimatley, my goal will be to figure out if there is a certain day and time to recieve the most comments.
from csv import reader
import datetime as dt #import datetime module for manipulating dates & times
opened_file = open('hacker_news.csv')
read_file = reader(opened_file)
hn = list(read_file)
print(hn[:5]) #display the first five rows of the hn file
[['id', 'title', 'url', 'num_points', 'num_comments', 'author', 'created_at'], ['12224879', 'Interactive Dynamic Video', 'http://www.interactivedynamicvideo.com/', '386', '52', 'ne0phyte', '8/4/2016 11:52'], ['10975351', 'How to Use Open Source and Shut the Fuck Up at the Same Time', 'http://hueniverse.com/2016/01/26/how-to-use-open-source-and-shut-the-fuck-up-at-the-same-time/', '39', '10', 'josep2', '1/26/2016 19:30'], ['11964716', "Florida DJs May Face Felony for April Fools' Water Joke", 'http://www.thewire.com/entertainment/2013/04/florida-djs-april-fools-water-joke/63798/', '2', '1', 'vezycash', '6/23/2016 22:20'], ['11919867', 'Technology ventures: From Idea to Enterprise', 'https://www.amazon.com/Technology-Ventures-Enterprise-Thomas-Byers/dp/0073523429', '3', '1', 'hswarna', '6/17/2016 0:01']]
headers = hn[0] #first row of data get assigned to variable called headers
hn = hn[1:]
print(headers) #display the headers
print('\n')
print(hn[:5]) #display the first 5 rows
['id', 'title', 'url', 'num_points', 'num_comments', 'author', 'created_at'] [['12224879', 'Interactive Dynamic Video', 'http://www.interactivedynamicvideo.com/', '386', '52', 'ne0phyte', '8/4/2016 11:52'], ['10975351', 'How to Use Open Source and Shut the Fuck Up at the Same Time', 'http://hueniverse.com/2016/01/26/how-to-use-open-source-and-shut-the-fuck-up-at-the-same-time/', '39', '10', 'josep2', '1/26/2016 19:30'], ['11964716', "Florida DJs May Face Felony for April Fools' Water Joke", 'http://www.thewire.com/entertainment/2013/04/florida-djs-april-fools-water-joke/63798/', '2', '1', 'vezycash', '6/23/2016 22:20'], ['11919867', 'Technology ventures: From Idea to Enterprise', 'https://www.amazon.com/Technology-Ventures-Enterprise-Thomas-Byers/dp/0073523429', '3', '1', 'hswarna', '6/17/2016 0:01'], ['10301696', 'Note by Note: The Making of Steinway L1037 (2007)', 'http://www.nytimes.com/2007/11/07/movies/07stein.html?_r=0', '8', '2', 'walterbell', '9/30/2015 4:12']]
ask_posts = [] #an empty list for each of the 3 types of Hacker News Posts
show_posts = []
other_posts = []
for row in hn: #loop thru each row
title = row[1]
title = title.lower() #make the title lower case
if title.startswith('ask hn') == True:
ask_posts.append(row) #if the title starts with ask hn, append it to ask_posts
elif title.startswith('show hn') == True:
show_posts.append(row) #if the title starts with show hn, append it to show_posts
else:
other_posts.append(row) #if it does not star with either, it gets appended to other_posts
#show the number of posts per type
print('There are', len(ask_posts), 'of Ask_HN Posts ') #print this specific string
print('There are', len(show_posts), 'of Show_HN Posts')
print('There are', len(other_posts), 'of Other Posts')
print('\n')
print(ask_posts[:5]) #show the first 5 rows of each list
print('\n')
print(show_posts[:5])
print('\n')
print(other_posts[:5])
There are 1744 of Ask_HN Posts There are 1162 of Show_HN Posts There are 17194 of Other Posts [['12296411', 'Ask HN: How to improve my personal website?', '', '2', '6', 'ahmedbaracat', '8/16/2016 9:55'], ['10610020', 'Ask HN: Am I the only one outraged by Twitter shutting down share counts?', '', '28', '29', 'tkfx', '11/22/2015 13:43'], ['11610310', 'Ask HN: Aby recent changes to CSS that broke mobile?', '', '1', '1', 'polskibus', '5/2/2016 10:14'], ['12210105', 'Ask HN: Looking for Employee #3 How do I do it?', '', '1', '3', 'sph130', '8/2/2016 14:20'], ['10394168', 'Ask HN: Someone offered to buy my browser extension from me. What now?', '', '28', '17', 'roykolak', '10/15/2015 16:38']] [['10627194', 'Show HN: Wio Link ESP8266 Based Web of Things Hardware Development Platform', 'https://iot.seeed.cc', '26', '22', 'kfihihc', '11/25/2015 14:03'], ['10646440', 'Show HN: Something pointless I made', 'http://dn.ht/picklecat/', '747', '102', 'dhotson', '11/29/2015 22:46'], ['11590768', 'Show HN: Shanhu.io, a programming playground powered by e8vm', 'https://shanhu.io', '1', '1', 'h8liu', '4/28/2016 18:05'], ['12178806', 'Show HN: Webscope Easy way for web developers to communicate with Clients', 'http://webscopeapp.com', '3', '3', 'fastbrick', '7/28/2016 7:11'], ['10872799', 'Show HN: GeoScreenshot Easily test Geo-IP based web pages', 'https://www.geoscreenshot.com/', '1', '9', 'kpsychwave', '1/9/2016 20:45']] [['12224879', 'Interactive Dynamic Video', 'http://www.interactivedynamicvideo.com/', '386', '52', 'ne0phyte', '8/4/2016 11:52'], ['10975351', 'How to Use Open Source and Shut the Fuck Up at the Same Time', 'http://hueniverse.com/2016/01/26/how-to-use-open-source-and-shut-the-fuck-up-at-the-same-time/', '39', '10', 'josep2', '1/26/2016 19:30'], ['11964716', "Florida DJs May Face Felony for April Fools' Water Joke", 'http://www.thewire.com/entertainment/2013/04/florida-djs-april-fools-water-joke/63798/', '2', '1', 'vezycash', '6/23/2016 22:20'], ['11919867', 'Technology ventures: From Idea to Enterprise', 'https://www.amazon.com/Technology-Ventures-Enterprise-Thomas-Byers/dp/0073523429', '3', '1', 'hswarna', '6/17/2016 0:01'], ['10301696', 'Note by Note: The Making of Steinway L1037 (2007)', 'http://www.nytimes.com/2007/11/07/movies/07stein.html?_r=0', '8', '2', 'walterbell', '9/30/2015 4:12']]
total_ask_comments = 0
for row in ask_posts: #use a loop to iterate thru the ask posts
num_comments = row[4] #num_comments is the 5th column so it is assigned index 4
num_comments = int(num_comments) #convert that to an integer
total_ask_comments += num_comments #add this value to the total_ask_comments
avg_ask_comments = total_ask_comments / len(ask_posts)
print(avg_ask_comments)
print('\n')
total_show_comments = 0 #to begin, assign total_show to zero
for row in show_posts: #loop thru the show_posts
num_comments = row[4] #num_comments is the 5th column so it is assigned index 4
num_comments = int(num_comments) #convert it to an integer
total_show_comments += num_comments #add this value to the total_show_comments
avg_show_comments = total_show_comments / len(show_posts) #average number of show comments
print(avg_show_comments)
14.038417431192661 10.31669535283993
### It looks like Ask_HN posts get more average comments than Show_HN posts.
### Since Ask_HN posts are likely to get more comments, I will focus the rest of
### my analysis on these types of posts.
-Calculate the amount of ask posts created in each hour of the day, along with the number of comments received.
-Calculate the average number of comments ask posts receive by hour created.
result_list = []
for row in ask_posts: #loop thru each row in the ask posts
created_at = row[6] # index 6 gets assigned to the variable created_at
num_comments = int(row[4]) #num_comments needs to be a int and can be found in row index 4
result_list.append([created_at, num_comments])
counts_by_hour = {} #empty dictionary called counts_by_hour
comments_by_hour = {} #empty dictionary called comments_by_hour
for row in result_list: #loop thru each row in the result_list
created_at = row[0] #extract the hour from the date
created_at = dt.datetime.strptime(created_at, '%m/%d/%Y %H:%M') #Use the datetime.strptime() method to parse the date and create a datetime object
created_at = created_at.strftime('%H') #select just the hour
if created_at not in counts_by_hour: #if created_at is not in counts_by_hour
counts_by_hour[created_at] = 1 #create a key in counts by hour and set it to 1
comments_by_hour[created_at] = row[1]
else:
counts_by_hour[created_at] += 1
comments_by_hour[created_at] += row[1]
avg_by_hour = [] #empty list called avg_by_hour
for hour in comments_by_hour: #loop thru the comments by hour dict earlier
hour_avg = comments_by_hour[hour] / counts_by_hour[hour]
avg_by_hour.append([hour, hour_avg]) #append the key value hour, hour_avg to the avg_by_hour list
print(avg_by_hour)
[['09', 5.5777777777777775], ['13', 14.741176470588234], ['10', 13.440677966101696], ['14', 13.233644859813085], ['16', 16.796296296296298], ['23', 7.985294117647059], ['12', 9.41095890410959], ['17', 11.46], ['15', 38.5948275862069], ['21', 16.009174311926607], ['20', 21.525], ['02', 23.810344827586206], ['18', 13.20183486238532], ['03', 7.796296296296297], ['05', 10.08695652173913], ['19', 10.8], ['01', 11.383333333333333], ['22', 6.746478873239437], ['08', 10.25], ['04', 7.170212765957447], ['00', 8.127272727272727], ['06', 9.022727272727273], ['07', 7.852941176470588], ['11', 11.051724137931034]]
swap_avg_by_hour = [] #create an empty list called swap_avg_by_hour
for row in avg_by_hour: #loop thru avg_by_hour
swap_avg_by_hour.append([row[1], row[0]]) #Iterate over the rows of avg_by_hour and append to swap_avg_by_hour a list whose first element is the second element of the row, and whose second element is the first element. the row
sorted_swap = sorted(swap_avg_by_hour, reverse = True) #sort swap_avg_by_hour in descending order of average number of comments.
print('Top 5 Hours for Ask Posts Comments')
for row in sorted_swap[:5]:
hour = dt.datetime.strptime(row[1], '%H') #formatting the hours using the datetime.strptime() constructor to return a datetme object.
hour = hour.strftime('%H:00') #use the strftime() method to specify the format of the time.
string = '{h}: {a:.2f} average comments per post'.format(h = hour, a = row[0]) # print the floowing string which will include average comments per post.
print(string)
Top 5 Hours for Ask Posts Comments 15:00: 38.59 average comments per post 02:00: 23.81 average comments per post 20:00: 21.52 average comments per post 16:00: 16.80 average comments per post 21:00: 16.01 average comments per post