Luca Delanglade - Nicolas Lamy
Notre étude porte sur les livres prêtés en bibliothèques à Paris:
https://opendata.paris.fr/explore/dataset/tous-les-documents-des-bibliotheques-de-pret/information/
Notre dataset contient les informations relatives au pret de chaque document disponible à l'emprunt et comptabilise le nombre de prets enregistrés sur l'année 2017. Nous avons souhaité le compléter avec des données accesibles sur l'API Googlebook.
Notre travail s'organise autour de 3 notebook:
-notebook Data Preprocessing -- traitements éffectués en amont pour l'import sur Neo4J
-notebook Data Visualisation -- analyser la distribution des données et restreindre l'étude
-notebook Googlebook scrapping -- permet d'ajouter une colonne de description des livres au dataset
Nous avons restreint notre étude à la catégorie litterature, qui comptabilise le plus grand nombre de prets à l'année : 200 000. Etant confronté à une limitation de 1000 requetes par jour via l'API Googlebook, nous avons importé les descriptions par batch de 1000.
import pandas as pd
import numpy as np
pd.set_option('max_colwidth', 200)
data_neo4J=pd.read_csv("./data/data_litterature.csv").drop(['Unnamed: 0'],axis=1)
data_neo4J.head()
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Titre |
sstitre |
Auteur |
Editeur |
Date |
prets |
Nombre de prêts par exemplaire |
exemplaires |
localisations |
Langue |
cat |
tauxemprunt |
0 |
Chanson douce |
|
Leïla Slimani |
Gallimard |
2016 |
1169.0 |
16.236111 |
72.0 |
51.0 |
français |
LFRA Litterature francaise |
68.0 |
1 |
Petit pays |
|
Gaël Faye |
Bernard Grasset |
2016 |
889.0 |
14.338710 |
62.0 |
47.0 |
français |
LFRA Litterature francaise |
60.0 |
2 |
Sur les chemins noirs |
|
Sylvain Tesson |
Gallimard |
2016 |
856.0 |
16.150943 |
53.0 |
49.0 |
français |
LFRA Litterature francaise |
67.0 |
3 |
Arrête avec tes mensonges |
|
Philippe Besson |
Julliard |
2017 |
846.0 |
16.588235 |
51.0 |
49.0 |
français |
LFRA Litterature francaise |
69.0 |
4 |
Article 353 du code pénal |
|
Tanguy Viel |
les Éditions de Minuit |
2017 |
785.0 |
14.811321 |
53.0 |
52.0 |
français |
LFRA Litterature francaise |
62.0 |
from neo4j import GraphDatabase
DB_URI = "bolt://localhost:7687"
DB_USER = "neo4j"
DB_PASSWORD = "0207"
driver = GraphDatabase.driver(DB_URI, auth=(DB_USER, DB_PASSWORD))
#Contraintes
CONTRAINTES=[
#On identifie un ouvrage par son titre et son auteur
"CREATE CONSTRAINT ON (l:Livre) ASSERT (l.titre, l.auteur) IS NODE KEY;",
#On affecte des valeurs unique pour le nom de l'auteur,de l'éditeur et le nom de la catégorie.
"CREATE CONSTRAINT ON (a:Auteur) ASSERT a.nomauteur IS UNIQUE;",
"CREATE CONSTRAINT ON (e:Editeur) ASSERT e.nomediteur IS UNIQUE;",
"CREATE CONSTRAINT ON (c: Categorie) ASSERT c.nomcat IS UNIQUE;"]
for i in CONTRAINTES:
with driver.session() as session:
session.run(i)
#Import des données principales.
#On rassemble les différentes informations des ouvrages
IMPORT1="""
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///data_litterature.csv'
AS ligne with ligne where ligne.Titre is not null
#Création d'un noeud Livre
MERGE (l:Livre {titre: trim(ligne.Titre), auteur: trim(ligne.Auteur)})
#Ajout (ou met à jour) une propriété 'prets' à livre
ON CREATE SET l.prets = ToInteger(ligne.prets)
ON MATCH SET l.prets = l.prets + ToInteger(ligne.prets)
ON CREATE SET l.exemplaires = ToInteger(ligne.exemplaires)
ON MATCH SET l.exemplaires = l.exemplaires + ToInteger(ligne.exemplaires)
ON CREATE SET l.localisations = ToInteger(ligne.localisations)
ON MATCH SET l.localisations = l.localisations + ToInteger(ligne.localisations)
ON CREATE SET l.soustitre = trim(ligne.sstitre)
ON CREATE SET l.langue = trim(ligne.Langue)
#Concaténation des maisons d'éditions
SET l.editions =COALESCE(l.editions,[]) +
CASE WHEN NOT (trim(ligne.Editeur) +"_"+ trim(ligne.Date)) IN COALESCE(l.editions,[])
THEN (trim(ligne.Editeur) +"_"+ trim(ligne.Date))
END
#Concaténation des dates
SET l.date=COALESCE(l.date,[]) +
CASE WHEN NOT ToInteger(ligne.Date) IN COALESCE(l.date,[])
THEN ToInteger(ligne.Date)
END
#Création d'une propriété taux d'emprunt
SET l.tauxemprunt =round(100-(24-l.prets/l.exemplaires)*100*0.0416666666)
#Création du noeud auteur
MERGE (auteur:Auteur { nomauteur: trim(ligne.Auteur) })
#Création du noeud editeur
MERGE (edi:Editeur { nomediteur: trim(ligne.Editeur) })
#Création du noeud catégorie
MERGE (cat:Categorie { nomcat: trim(ligne.cat)})
#Création de relation
MERGE (l)-[: ECRIT]->(auteur)
MERGE (l)-[: EDITE]->(edi)
MERGE (l)-[: APPARTIENT]->(cat) ;
"""
with driver.session() as session:
session.run(IMPORT1)
#Import des données de GoogleBook
IMPORT2="""
LOAD CSV WITH HEADERS FROM 'file:///Googlebook_db.csv'
AS ligne with ligne where ligne.Titre is not null
#Ajout d'une propriété summary de GoogleBook
MERGE (l:Livre {titre: trim(ligne.Titre)}) SET l.summary = trim(ligne.Summary)
"""
with driver.session() as session:
session.run(IMPORT2)
#Qui sont les auteurs les plus lus?
REQUETE1="""
MATCH (c:Categorie)--(l:Livre)--(a:Auteur)
WITH a,c, collect(l.titre) as l ,collect(l.prets) as p, reduce(total=0, number in collect (l.prets) | total + number) as psum
RETURN a.nomauteur , l, p, psum, right(c.nomcat,length(c.nomcat)-4)
ORDER BY psum DESC
LIMIT 10
"""
with driver.session() as session:
result=session.run(REQUETE1)
df = pd.DataFrame(result, columns=["Auteur","Ouvrages","prets","Total prets","Catégorie"])
#Fonction pour trier les résultats par nombre de prets et faire un Top 5 des ouvrages pour chaque auteur
def func(x,y):
r=pd.DataFrame(x,y).sort_values(by=0,ascending=False)
return list(r.index), list(r.values.reshape(-1))
df["Top 5 Ouvrages"]=df.apply(lambda x:func(x[2],x[1])[0][:5],axis=1)
df["Top 5 prets"]=df.apply(lambda x:func(x[2],x[1])[1][:5],axis=1)
df=df.drop(["Ouvrages"],axis=1)[["Auteur","Total prets","Catégorie", "Top 5 Ouvrages", "Top 5 prets"]]
df.head(20)
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Auteur |
Total prets |
Catégorie |
Top 5 Ouvrages |
Top 5 prets |
0 |
Anne Perry |
6089 |
Litterature britannique |
[Un Noël à New York, Vengeance en eau froide, Un traître à Kensington Palace, Bryanston Mews, Meurtre en écho] |
[555, 401, 296, 221, 213] |
1 |
Harlan Coben |
5767 |
Litterature nord-americaine |
[Intimidation, Six ans déjà, Tu me manques, À toute épreuve, Ne t'éloigne pas] |
[725, 432, 344, 301, 283] |
2 |
Michael Connelly |
5716 |
Litterature nord-americaine |
[Mariachi Plaza, Jusqu'à l'impensable, Les dieux du verdict, Dans la ville en feu, Ceux qui tombent] |
[492, 469, 398, 307, 233] |
3 |
Fred Vargas |
5283 |
Litterature francaise |
[Temps glaciaires, Quand sort la recluse, Un lieu incertain, Sans feu ni lieu, L'homme à l'envers] |
[632, 595, 406, 364, 362] |
4 |
Amélie Nothomb |
5272 |
Litterature francaise |
[Frappe-toi le coeur, Riquet à la houppe, La nostalgie heureuse, Le crime du comte Neville, Pétronille] |
[633, 613, 343, 340, 332] |
5 |
Mary Higgins Clark |
4973 |
Litterature nord-americaine |
[Le piège de la Belle au bois dormant, La mariée était en blanc, Le temps des regrets, Noir comme la mer, La boîte à musique] |
[495, 444, 380, 351, 308] |
6 |
Henning Mankell |
4499 |
Litterature nordique |
[Les bottes suédoises, Une main encombrante, Les chaussures italiennes, Sable mouvant, Un paradis trompeur] |
[537, 399, 293, 202, 199] |
7 |
Joyce Carol Oates |
4380 |
Litterature nord-americaine |
[Valet de pique, Sacrifice, Daddy Love, Dahlia noir & Rose blanche, Carthage] |
[456, 426, 215, 185, 166] |
8 |
Stephen King |
4342 |
Litterature nord-americaine |
[Fin de ronde, Le bazar des mauvais rêves, Carnets noirs, Mr Mercedes, Revival] |
[313, 293, 273, 248, 243] |
9 |
James Patterson |
4338 |
Litterature nord-americaine |
[Cours, Alex Cross !, Tue-moi si tu peux, 14e péché mortel, Invisible, Cross, coeur de cible] |
[229, 216, 216, 201, 174] |
Le top trois des auteurs les plus lus sont Anne Perry, Harlan Coben et Michael Connely.
#Quels sont les livres américains les plus lus?
REQUETE2="""
MATCH (cat)--(l:Livre)--(a:Auteur)
MATCH (l:Livre)--(e:Editeur)
WHERE left(cat.nomcat,4)="LNAM"
WITH collect(e.nomediteur) as e, a, l
RETURN DISTINCT(l.titre),a.nomauteur,e, l.langue, l.prets
ORDER BY l.prets DESC
LIMIT 20
"""
with driver.session() as session:
result=session.run(REQUETE2)
df = pd.DataFrame(result, columns=["Titre","Auteur","Editeurs","Langue","Prets"])
df.head(10)
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Titre |
Auteur |
Editeurs |
Langue |
Prets |
0 |
Intimidation |
Harlan Coben |
[Pocket, Feryane, Belfond] |
français |
725 |
1 |
Divergente |
Veronica Roth |
[Pocket jeunesse, Éd. France loisirs, Nathan] |
français |
617 |
2 |
Message sans réponse |
Patricia J. MacDonald |
[Editions Libra diffusio, Albin Michel] |
français |
597 |
3 |
La vengeance des mères |
Jim Fergus |
[Pocket, A vue d'oeil, Cherche midi] |
français |
539 |
4 |
The girls |
Emma Cline |
[Vintage, Random House, Chatto & Windus, Quai Voltaire] |
français |
521 |
5 |
Le trône de fer |
George R. R. Martin |
[Pygmalion, J'ai lu] |
français |
506 |
6 |
Une avalanche de conséquences |
Elizabeth George |
[Pocket, Presses de la Cité] |
français |
495 |
7 |
Le piège de la Belle au bois dormant |
Mary Higgins Clark |
[Albin Michel] |
français |
495 |
8 |
Mariachi Plaza |
Michael Connelly |
[Le Livre de poche, Calmann-Lévy] |
français |
492 |
9 |
Le vieux saltimbanque |
Jim Harrison |
[J'ai lu, Flammarion] |
français |
482 |
#Les livres américains les plus lus sont Intimidation et Divergente.
#On remarque qu'Intimidation, le livre le plus lu à été écrit par le deuxième auteur le plus lu (Harlan Coben).
#On retrouve le trone de fer dans le top 10.
#Quels sont les Livres les plus difficiles à emprunter?
# Le Taux emprunt est de 100% pour 2 emprunts par mois par exemplaire.
# On estime qu'un livre est emprunté pour 15 jours, il faut deux emprunts pour que le livre soit emprunté un mois.
REQUETE3="""
MATCH (cat)--(l:Livre)--(a:Auteur)
MATCH (l:Livre)--(e:Editeur)
WITH a,l,collect(distinct(e.nomediteur)) as e
RETURN l.titre, a.nomauteur, e, l.langue, l.tauxemprunt
ORDER BY l.tauxemprunt DESC
LIMIT 20
"""
pd.set_option('max_colwidth', 300)
with driver.session() as session:
result=session.run(REQUETE3)
df = pd.DataFrame(result, columns=["Titre","Auteur","Editeurs","Langue","Taux d'emprunt"])
df.head(10)
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Titre |
Auteur |
Editeurs |
Langue |
Taux d'emprunt |
0 |
Le café chat |
Melissa Daley |
[City éditions] |
français |
88.0 |
1 |
L'école du crime |
Christian Jacq |
[J éditions;XO] |
français |
79.0 |
2 |
Sphinx |
Christian Jacq |
[XO éditions] |
français |
75.0 |
3 |
Vengeance haute couture |
Rosalie Ham |
[Mosaïc] |
français |
71.0 |
4 |
De pourpre et de soie |
Mary Chamberlain |
[Préludes] |
français |
71.0 |
5 |
Les disparues de Shanghai |
Peter May |
[Actes Sud;Leméac] |
français |
71.0 |
6 |
La promesse |
Cédric Cham |
[Éditions Fleur sauvage] |
français |
71.0 |
7 |
Zui man chang de na yi ye |
Jun Cai |
[Xian dai chu ban she] |
chinois |
67.0 |
8 |
La Fin de l'été |
Danielle Steel |
[Presses de la Cité] |
français |
67.0 |
9 |
Vingt-quatre heures pour convaincre une femme |
Philippe Lacoche |
[Écriture] |
français |
67.0 |
Le top trois des livres les plus difficiles à emprunter sont le café chat, l'école du crime et sphinx.
#Quels auteurs sont les mieux représentés en bibliothèque?
REQUETE4="""
MATCH (c:Categorie)--(l:Livre)--(a:Auteur)
WITH a, count(distinct(l.titre)) as rel, collect(l.titre) as l, collect(l.prets) as p, c, collect(l.exemplaires) as ex
RETURN a.nomauteur, l,p,rel,right(c.nomcat,length(c.nomcat)-4),ex
ORDER BY rel DESC
LIMIT 20
"""
with driver.session() as session:
result=session.run(REQUETE4)
df = pd.DataFrame(result,columns=["Auteur","Titres","prets","Nombre d'ouvrages","Catégorie","Exemplaires"])
df["Top 5 Ouvrages"]=df.apply(lambda x:func(x[2],x[1])[0][:5],axis=1)
df["Top 5 prets"]=df.apply(lambda x:func(x[2],x[1])[1][:5],axis=1)
df["Total prets"]=df.apply(lambda x:np.sum(x[2]),axis=1)
df["Total exemplaires"]=df.apply(lambda x:np.sum(x[5]),axis=1)
df=df.drop(["Titres","Exemplaires"],axis=1)[["Auteur","Nombre d'ouvrages","Catégorie", "Top 5 Ouvrages", "Top 5 prets", "Total prets","Total exemplaires"]]
df.head(20)
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Auteur |
Nombre d'ouvrages |
Catégorie |
Top 5 Ouvrages |
Top 5 prets |
Total prets |
Total exemplaires |
0 |
Georges Simenon |
207 |
Litterature francaise |
[Oeuvre romanesque, Tout Simenon, Tout Maigret, Les caves du Majestic, 0Romans] |
[622, 267, 186, 111, 101] |
3199 |
977 |
1 |
Agatha Christie |
199 |
Litterature britannique |
[Agatha Christie, Dix petits nègres, Le meurtre de Roger Ackroyd, Le Noël d'Hercule Poirot, L'if et la rose] |
[759, 195, 141, 92, 89] |
4237 |
1029 |
2 |
Honoré de Balzac |
138 |
Litterature francaise |
[La comédie humaine, Le père Goriot, Eugénie Grandet, La peau de chagrin, Le colonel Chabert] |
[531, 181, 170, 170, 140] |
3537 |
1624 |
3 |
James Patterson |
135 |
Litterature nord-americaine |
[Cours, Alex Cross !, Tue-moi si tu peux, 14e péché mortel, Invisible, Cross, coeur de cible] |
[229, 216, 216, 201, 174] |
4338 |
1211 |
4 |
Danielle Steel |
125 |
Litterature nord-americaine |
[Le fils prodigue, Une vie parfaite, Coup de foudre, Musique, Ambitions] |
[284, 207, 202, 181, 179] |
4168 |
1069 |
5 |
Stephen King |
124 |
Litterature nord-americaine |
[Fin de ronde, Le bazar des mauvais rêves, Carnets noirs, Mr Mercedes, Revival] |
[313, 293, 273, 248, 243] |
4342 |
1406 |
6 |
Alexandre Dumas |
124 |
Litterature francaise |
[Les trois mousquetaires, Le comte de Monte-Cristo, Le Comte de Monte-Cristo, La dame aux camélias, La reine Margot] |
[274, 224, 154, 143, 72] |
1968 |
1042 |
7 |
Anne Perry |
118 |
Litterature britannique |
[Un Noël à New York, Vengeance en eau froide, Un traître à Kensington Palace, Bryanston Mews, Meurtre en écho] |
[555, 401, 296, 221, 213] |
6089 |
1310 |
8 |
Guy de Maupassant |
110 |
Litterature francaise |
[Une vie, Bel-Ami, Contes et nouvelles, Le Horla, Pierre et Jean] |
[249, 249, 230, 227, 147] |
2806 |
1001 |
9 |
Nora Roberts |
110 |
Litterature nord-americaine |
[Des baisers sous la neige, Le menteur, L'auberge du mystère, Un coeur naufragé, Sasha] |
[201, 191, 183, 183, 173] |
2657 |
771 |
10 |
Joyce Carol Oates |
105 |
Litterature nord-americaine |
[Valet de pique, Sacrifice, Daddy Love, Dahlia noir & Rose blanche, Carthage] |
[456, 426, 215, 185, 166] |
4380 |
1490 |
11 |
Jules Verne |
100 |
Litterature francaise |
[Voyage au centre de la terre, Le tour du monde en 80 jours, Vingt mille lieues sous les mers, L'île mystérieuse, 20 000 lieues sous les mers] |
[178, 157, 99, 86, 77] |
1616 |
841 |
12 |
Terry Pratchett |
100 |
Litterature britannique |
[La longue terre, La huitième couleur, Fond d'écran, De bons présages, La longue utopie] |
[96, 84, 72, 66, 65] |
1705 |
901 |
13 |
Juliette Benzoni |
100 |
Litterature francaise |
[Le vol du Sancy, Suite italienne, La petite peste et le chat botté, La fille du condamné, Les trois frères] |
[160, 139, 134, 109, 102] |
2071 |
787 |
14 |
Victor Hugo |
99 |
Litterature francaise |
[Les Misérables, Les misérables, Notre-Dame de Paris, L'homme qui rit, Roman] |
[361, 225, 217, 145, 111] |
2727 |
1365 |
15 |
George Sand |
95 |
Litterature francaise |
[La petite Fadette, François le Champi, Consuelo, Marianne, Oeuvres autobiographiques] |
[86, 76, 61, 52, 51] |
1066 |
597 |
16 |
Serge Brussolo |
95 |
Litterature francaise |
[L'oiseau des tempêtes, Tambours de guerre, Dortoir interdit, Cheval rouge, Le chat aux yeux jaunes] |
[152, 106, 68, 60, 58] |
1100 |
483 |
17 |
Ruth Rendell |
94 |
Litterature britannique |
[Les coins obscurs, Celle qui savait tout, Bon voisinage, Une vie si convenable, Un rossignol sans jardin] |
[471, 218, 198, 165, 164] |
2696 |
899 |
18 |
Henry James |
94 |
Litterature nord-americaine |
[0Nouvelles complètes, Daisy Miller, Le tour d'écrou, Ce que savait Maisie, Portrait de femme] |
[86, 85, 79, 70, 70] |
1251 |
700 |
19 |
Michel Peyramaure |
94 |
Litterature francaise |
[Couleurs Venise, La maison des tourbières, Le sabre de l'Empire, Trois cavaliers dans la forêt, Les rivales] |
[150, 90, 79, 65, 62] |
1071 |
580 |
Le top trois des auteurs les mieux représentés en bibliothèque sont Georges Simenon, Agatha Christie et Honoré de Balzac.
#Nous souhaitons voir quels sont les derniers livres édités par Gallimard qui sont disponibles à l'emprunt
REQUETE5="""
MATCH (e:Editeur{nomediteur:"Gallimard"})--(l:Livre)--(a:Auteur)
WHERE l.date IS NOT NULL
RETURN l.titre,a.nomauteur,reduce(m=0, t IN l.date | CASE WHEN m > t THEN m ELSE t END) as lastedition, l.tauxemprunt
ORDER BY lastedition DESC
LIMIT 20
"""
with driver.session() as session:
result=session.run(REQUETE5)
df = pd.DataFrame(result, columns=["Titre","Auteur","Date","Taux d'emprunt"])
df.head(10)
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
|
Titre |
Auteur |
Date |
Taux d'emprunt |
0 |
Le coeur content |
Nanoucha Van Moerkerkenland |
2018 |
0.0 |
1 |
Casse-gueule |
Clarisse Gorokhoff |
2018 |
0.0 |
2 |
Je voulais leur dire mon amour |
Jean-Noël Pancrazi |
2018 |
0.0 |
3 |
Erri de Luca, entre Naples et la Bible |
Henri Godard |
2018 |
0.0 |
4 |
Lynwood Miller |
Sandrine Roy |
2018 |
0.0 |
5 |
Le syndrome de Garcin |
Jérôme Garcin |
2018 |
0.0 |
6 |
Tous les chats sautent à leur façon |
Herta Müller |
2018 |
0.0 |
7 |
Et moi, je vis toujours |
Jean d' Ormesson |
2018 |
0.0 |
8 |
Les garçons de l'été |
Rebecca Lighieri |
2018 |
17.0 |
9 |
Un si beau diplôme ! |
Scholastique Mukasonga |
2018 |
0.0 |
Les deux derniers livres édités par Gallimard qui sont disponibles à l'emprunt sont "Le coeur conten"t et "Casse-gueule"