图书推荐系统(一)之数据准备

📖对豆瓣图书的数据集进行分析,方案一根据图书分析用户数,方案二根据用户分析图书数

1 数据准备

来自 豆瓣图书数据集,表结构是用户id-图书id-评分。

2 数据分析

2.1 根据图书分析用户数

思路:分析用户评分最多的和最小的N本图书对应的评分用户数。

(1)加载数据集,放入字典结构

def _load_data(file_path):
	book_rate_map = dict()
	for line in open(file_path,"r",encoding="utf-8").readlines():
		 user,bookid,rate = line.strip().split("::")
		 #book_rate_map={bookid:{user:score}}
		 book_rate_map.setfault(bookid,{})
		 book_rate_map[bookid][user] = score
return book_rate_map					

(2)获取评分最多的和最少的N本图书

def _most_rate_books(k):
	book_rate_score = _load_data("./data/douban.dat")
	#图书id-评分人数数据集
  book_rate_num = dict()
  #用户名数据集,set()函数创建一个无序不重复元素集
  users = set()
	#计算每本图书下的用户数,以及展示用户
	for key in book_rate_score.keys():
		book_rate_num[key] =len(book_rate_score[key])
		for user in book_rate_score[key].keys():
			users.add(user)
	#按照评分人数,从大到小排序
	new_book_rate_num = sorted(book_rate_num.items(),key = lambda k:k[1],reverse = True)
	print("总有图书数目:{}".format(new_book_rate_num.__len__()))
	print("总有用户数目:{}".format(users.__len__()))
	#按照评分人数,从小到大排序
	new_1_book_rate_num = sorted(book_rate_num.items(),key = lambda k:k[1],reverse = False)
	#返回评分最多的和最少的N本图书id列表+原数据集
	return list(dict(new_book_rate_num[:k]).keys())+list(dict(new_1_book_rate_num[:k]).keys()),book_rate_score

(3)获取用户评分最多的和最小的N本图书对应的评分用户

def _topk_book_to_user():
	user = set()
	books,book_rate_score = _most_rate_books(30):
		for book in books:
			for user in book_rate_score[book].keys():
				users.add(user)
			print(users.__user__)

完整代码如下: analysis_topK_book_to_users.py

# -*- coding: utf-8 -*-
"""
    Author:JinHelen
    Date:2019-04-16
    Desc:分析豆瓣数据集中评分最多的N本图书和最少的N本图书涉及的用户数
    思路:
    1、加载数据,返回字典结构,数据集形式为:{bookid:{user:score}}
    2、要获取用户评分最多的和最小的N本图书对应的评分用户数
    (1)计算每本图书下的用户数,得到图书id-用户数数据表,记录下用户名
    (2)按照评分人数,采用倒排和正排,分别取前N本图书
    (3)返回2N本图书id和原数据集
    (4)遍历得到的2N本图书id,获取每本图书下的用户名,计算用户数
"""

#加载数据集,返回字典结构
def _load_data(file_path):
    book_rate_map = dict()
    for line in open(file_path,"r",encoding="utf-8").readlines():
        user, bookid, score = line.strip().split("::")
        #book_rate_map={bookid:{user:score}}
        book_rate_map.setdefault(bookid,{})
        book_rate_map[bookid][user]=score
    return book_rate_map
#获取用户评分最多的和最少的N本图书,以及图书评分字典
def _most_rate_books(k):
    #图书id-用户-评分数据集
    book_rate_score = _load_data("./data/douban.dat")
    #图书id-用户数数据集
    book_rate_num = dict()
    #用户名数据集,set()函数创建一个无序不重复元素集
    users = set()
    #这里的keys是指bookid
    for key in book_rate_score.keys():
        #计算bookid下的用户数
        book_rate_num[key] = len(book_rate_score[key])
        #这里的keys指user
        for user in book_rate_score[key].keys():
            #存下用户名
            users.add(user)
    #按照评分人数倒排,revers=True 表示从大到小排序
    # 图书id-用户数数据集 从大到小
    new_book_rate_num = sorted(book_rate_num.items(),key= lambda k:k[1],reverse=True)
    #__len__返回元素的个数
    print("总有图书数目:{}".format(new_book_rate_num.__len__()))
    print("总有用户数据:{}".format(users.__len__()))
    # print(dict(new_book_rate_num[:k]))
    # 按照评分人数正排,revers=False 表示从小到大排序
    # 图书id-用户数数据集 从小到大
    new_1_book_rate_num = sorted(book_rate_num.items(), key=lambda k: k[1], reverse=False)
    #返回评分最多的和最少的N本图书id+原数据集
    return list(dict(new_book_rate_num[:k]).keys())+list(dict(new_1_book_rate_num[:k]).keys()),book_rate_score

# 获取用户评分最多的和最小的N本图书对应的评分用户
def _topk_book_to_user():
    users = set()
    books, book_rate_score = _most_rate_books(30)
    for book in books:
        for user in book_rate_score[book].keys():
            users.add(user)
        print(users.__len__())

_topk_book_to_user()

运行结果部分内容:

总有图书数目:80008
总有用户数据:383033
2071
2200
4107
4248
4457
...
19153
19154
19155
19156
19156
注意:数字代表每本图书下的用户数

2.2 根据用户分析图书数

思路:分析豆瓣数据集中评分行为最多的和最少的用户涉及的图书数

(1)加载数据

def _load_data(file_path):
    user_rate_map = dict()
    for line in open(file_path,"r",encoding="utf-8").readlines():
        user, bookid, score = line.strip().split("::")
        #user_rate_map = {user:{bookid:score}}
        user_rate_map.setdefault(user,{})
        user_rate_map[user][bookid] = score
    return user_rate_map

(2)获取评分行为最多的M个用户和最少的N个用户

def _most_rate_users(most,small):
		user_rate_score = _load_data("./data/douban.dat")
		#用户-图书数数据集
		user_rate_num = dict()
		#图书id数据集
		books = set()
		for user in user_rate_score.keys():
				user_rate_num[user] = len(user_rate_score[user])
				for book in user_rate_score[user].keys():
						books.add(book)
		#按照图书书倒排,从大到小排序
		new_user_rate_num = sorted(user_rate_num.items(),key=lambda k:k[1],reverse=True)
		print("总有用户数目:{}".format(new_user_rate_num.__len__()))
		print("总有图书数目:{}".format(books.__len__()))
		#按照图书书正排,从小到大排序
		new_1_user_rate_num = sorted(user_rate_num.items(),key=lambda k:k[1],reverse=False)
	  return list(dict(new_user_rate_num[:most]).keys())+list(dict(new_1_user_rate_num[:small]).keys()),user_rate_score

(3)将对应的用户和图书id写入文件

def _write_users_and_books(users,books):
		fw = open("data/select_users.txt","w")
		fw.write("\n".join(users))
		fw.close()
		
		fw = open("data/select_books.txt","w")
		fw.write("\n".join(books))
		fw.close()

(4)获取用户和对应的图书数

def _top_user_to_book():
		book = set()
		users,user_rate_score = _most_rate_users(50,50)
		for user in users:
				for book in user_rate_score[user].keys():
						books.add(book)
				print(books.__len__())
				_write_users_and_books(users,list(books))

完整代码如下: analysis_topK_users_to_books.py

"""
    Author:JinHelen
    Date:2019-04-16
    Desc:分析豆瓣数据集中评分行为最多的和最少的用户涉及的图书数
    思路:
    1、加载数据,返回字典结构,数据集形式为:{user:{bookid:score}}
    2、要获取评分行为最多的M个和最少的N个用户
    (1)计算每名用户下的图书数,得到用户-图书数数据集,记录下图书id
    (2)按照图书数,采用倒排和正排,分别取前M个用户和前N个用户
    (3)返回M+N个用户和原数据集
    (4)遍历得到的M+N个用户,获取每个用户下的图书id,计算图书数
    3、将得到的M+N个用户存到txt中,得到的这些用户评价过的图书存到text中

"""
# 加载数据
def _load_data(file_path):
    user_rate_map = dict()
    for line in open(file_path,"r",encoding="utf-8").readlines():
        user, bookid, score = line.strip().split("::")
        #user_rate_map = {user:{bookid:score}}
        user_rate_map.setdefault(user,{})
        user_rate_map[user][bookid] = score
    return user_rate_map

#获取评分行为最多的M个用户和最少的N个用户
def _most_rate_users(most,small):
    #用户-图书id-评分数据集
    user_rate_score = _load_data("./data/douban.dat")
    #用户-图书数数据集
    user_rate_num = dict()
    #图书id数据集
    books = set()
    for user in user_rate_score.keys():
        user_rate_num[user] = len(user_rate_score[user])
        for book in user_rate_score[user].keys():
            books.add(book)
    # 按照图书数倒排,revers=True 表示从大到小排序
    new_user_rate_num = sorted(user_rate_num.items(),key=lambda k:k[1],reverse=True)
    print("总有用户数目:{}".format(new_user_rate_num.__len__()))
    print("总有图书数目:{}".format(books.__len__()))
    # print(dict(new_user_rate_num[:most]))

    # 按照图书数正排,revers=False 表示从小到大排序
    new_1_user_rate_num = sorted(user_rate_num.items(), key=lambda k: k[1], reverse=False)
    # print(dict(new_1_user_rate_num[:small]))

    return list(dict(new_user_rate_num[:most]).keys()) + list(dict(new_1_user_rate_num[:small]).keys()),user_rate_score

#将对应的用户和图书id写入文件
def _write_users_and_books(users,books):
    fw = open("data/select_users.txt","w")
    fw.write("\n".join(users))
    fw.close()

    fw = open("data/select_books.txt", "w")
    fw.write("\n".join(books))
    fw.close()

#获取用户和对应的图书数
def _top_user_to_book():
    books = set()
    users,user_rate_score = _most_rate_users(50,50)
    for user in users:
        for book in user_rate_score[user].keys():
            books.add(book)
        #每个用户下的图书数
        print(books.__len__())

        _write_users_and_books(users, list(books))


_top_user_to_book()

运行结果部分内容:

总有用户数目:383033
总有图书数目:80008
4110
5747
6765
7768
8330
...
24043
24043
24044
24046
注:数字分别代表每位用户下的图书数