PROJET AUTOBLOG


Sam et Max

source: Sam et Max

⇐ retour index

Le pandas c’est bon, mangez en

samedi 10 mai 2014 à 08:30

Ceci est un post invité de joshuafr posté sous licence creative common 3.0 unported.

Bonjour à tous, jeunes tailleurs de bambou, suite à un article d’introduction à numpy par le grand maître Sam Les bases de Numpy, je m’en vais vous présenter une lib qui roxx du poney dans le calcul numérique : Pandas.

Pour faire simple, Pandas apporte à Python la possibilité de manipuler de grands volumes de données structurées de manière simple et intuitive, chose qui faisait défaut jusqu’ici. Il y a bien eu quelques tentatives comme larry, mais rien n’avait jamais pu égaler les fonctionnalités du langage R. Aujourd’hui Pandas y arrive en fournissant notamment le célèbre type dataframe de R, avec en prime tout un tas d’outils pour agréger, combiner, transformer des données, et tout ça sans se casser le cul. Que du bonheur!

Donc pour commencer, on installe le bousin par un simple : pip install pandas qui va si vous ne l’avez pas déjà fait, aussi télécharger/compiler/installer tout un tas de librairies dont numpy. Je vous conseille aussi d’utiliser ipython afin d’avoir une meilleure interaction avec les libs, notamment avec matplotlib en utilisant le switch ipython --pylab afin d’avoir directement les graphiques en mode interactif, ainsi que toute la bibliothèque numpy directement importée (en interne, ipython fera un import numpy as np).
On appelle la bête d’un simple:

In [1]: import pandas as pd

Oui je sais, la grande classe…

Tout est Series

Le type de base en Pandas et la Series. On peut le voir comme un tableau de données à une dimension:

In [2]: pd.Series(np.arange(1,5))
Out[2]: 
0    1
1    2
2    3
3    4
dtype: int64

La colonne de gauche représente l’index de la Series, normalement unique pour chaque entrée. La colonne de droite correspond à nos valeurs sur lesquelles nous voulons travailler.
L’index n’est pas forcément une suite d’entiers, et la Series peut être nommée:

In [3]: s=pd.Series([1,2,3.14,1e6], index=list('abcd'), name='ma_series')
In [4]: s
Out[4]: 
a          1.00
b          2.00
c          3.14
d    1000000.00
Name: ma_series, dtype: float64

A noter qu’un type-casting est systématiquement appliqué afin d’avoir un tableau de type uniforme (ici le data-type est du float64) qui peut être modifié (dans une certaine mesure) via Series.astype.

Le slicing c’est comme du fisting avec une bonne dose de vaseline, ça glisse tout seul:

In [5]: s['b':'d']
Out[5]: 
b          2.00
c          3.14
d    1000000.00
Name: ma_series, dtype: float64

Et oui, la sélection par indexation se fait sur… l’index de la Series. Ainsi s['a'] renverra la ligne dont l’index est ‘a’, mais Pandas est assez intelligent pour reconnaître si on lui demande de nous renvoyer des valeurs suivant l’ordonnancement du tableau de valeurs (comme numpy). Ainsi s[0] renverra la première valeur du tableau, qui ici est égale à s['a'].
Là où ça peut poser problème c’est quand notre index est une suite d’entiers, comme par exemple avec x=pd.Series(np.arange(1,5), index=np.arange(1,5)). Si vous demandez x[1], Pandas ne retrouve pas ses petits et vous retournera une zolie KeyError. Pour ces cas ambigus, il existe l’indexation stricte sur le nom de index de la Series via x.loc[nom_d'index], et l’indexation stricte sur le numéro d’ordre dans le tableau via x.iloc[numéro_d'ordre]. Essayez x.loc[0] et x.iloc[0] pour vous rendre compte de la différence.
Comme pour les préliminaires où il est bon de tâter un peu de tout avec de pénétrer dans le vif du sujet, laissons pour le moment l’indexation sur laquelle nous reviendrons plus tard, pour regarder d’un peu plus près comment faire joujou avec nos valeurs.

Un peu à la manière des arrays de numpy, on peut appliquer des fonctions mathématiques directement sur la Serie, ou passer par des fonctions raccourcis:

In [6]: s.sum()
Out[6]: 1000006.14

Ce qui revient au même que de faire np.sum(s) (rappelez vous, ipython avec –pylab a importé numpy dans la variable np).

La fonction describe est bien utile pour avoir un aperçu rapide de ce à quoi on a affaire:

In [7]: s.describe()
Out[7]: 
count          4.000000
mean      250001.535000
std       499998.976667
min            1.000000
25%            1.750000
50%            2.570000
75%       250002.355000
max      1000000.000000
Name: ma_series, dtype: float64

ce qui donne le nombre de données, la moyenne globale, la déviation standard, le minimum, les quartiles et le maximum de la Serie.

Le truc à retenir est que c’est l’index qui est primordial dans un grand nombre d’opérations. Ainsi si l’on veut additionner 2 Series ensemble, il faut que leurs index soient alignés :

In [8]: s2=pd.Series(np.random.rand(4), index=list('cdef'), name='autre_serie')
 
In [9]: s+s2
Out[9]: 
a               NaN
b               NaN
c          4.021591
d    1000000.401511
e               NaN
f               NaN
dtype: float64

Ici, seuls les index ‘c’ et ‘d’ étaient présents dans les 2 Series, Pandas effectuant avant l’opération d’addition une union basée sur l’index. Les autres entrées sont marquées en NaN, soit Not a Number. Une possibilité pour contrer ce phénomène et de dire à Pandas de remplacer les résultats manquants lors de l’union par 0:

In [10]: s.add(s2, fill_value=0)
Out[10]: 
a          1.000000
b          2.000000
c          4.021591
d    1000000.401511
e          0.563508
f          0.655915
Name: ma_series, dtype: float64

Mais si ce sont uniquement les valeurs qui nous intéressent, et non les indexations, il est possible de les supprimer:

In [11]: s.reset_index(drop=True)+s2.reset_index(drop=True)
Out[11]: 
0          1.881591
1          2.401511
2          3.703508
3    1000000.655915
dtype: float64

Oh joie, oh bonheur, je peux faire ce que je veux avec mes cheveux, enfin mes données…

Et PAN! dans ta frame

La DataFrame est l’extension en 2 dimensions des Series. Elle peut être vue comme un empilement de Series dont les index sont partagés (et donc intrinsèquement alignés), ou comme dans un tableur où les index sont les numéros de lignes et les noms des Series les noms des colonnes. Je ne vais pas décrire toutes les manières de créer une DataFrame, sachez juste qu’on peut les obtenir à partir de dictionnaires, de liste de liste ou de liste de Series, d’arrays ou de records numpy, de fichier excel ou csv et même depuis des bases de données, de fichier JSON ou HTML, et depuis le presse-papiers.

In [14]: genre=[['femme','homme'][x] for x in np.random.random_integers(0,1,100)]
 
In [15]: lateral=[['droite','gauche'][x] for x in np.random.random_integers(0,1,100)]
 
In [16]: age=np.random.random_integers(1,100,100)
 
In [17]: df=pd.DataFrame({'Genre':genre, 'Lateral':lateral, 'Age':age})
 
In [18]: df
Out[18]: 
    Age  Genre Lateral
0    69  femme  droite
1    46  homme  droite
2    89  homme  droite
3    14  homme  droite
4    74  homme  droite
5     5  femme  gauche
6    66  femme  droite
7    73  homme  gauche
8    99  homme  gauche
9    17  homme  gauche
    ...    ...     ...
 
[100 rows x 3 columns]

L’affichage par défaut depuis la version 0.13 est en mode ‘truncate’ où la fin de la DataFrame est tronquée suivant la hauteur de votre terminal, mais ça peut se changer via les divers paramètres à regarder sous pd.options.display.

Là donc nous avons une DataFrame de 3 colonnes (plus un index), chaque colonne étant en réalité une Serie :

In [20]: type(df['Age'])
Out[20]: pandas.core.series.Series

La sélection peut se faire de plusieurs manières, à chacun de choisir sa préférée (moi c’est Dafnée avec ses gros nénés). Ainsi pour avoir les 3 premières lignes des âges

In [21]: df['Age'][0:3]
Out[21]: 
0    69
1    46
2    89
Name: Age, dtype: int64
 
In [22]: df[0:3]['Age']
Out[22]: 
0    69
1    46
2    89
Name: Age, dtype: int64
 
In [23]: df.Age[0:3]
Out[23]: 
0    69
1    46
2    89
Name: Age, dtype: int64
 
In [24]: df.loc[0:3, 'Age']
Out[24]: 
0    69
1    46
2    89
3    14
Name: Age, dtype: int64

et oui, les noms de colonnes peuvent aussi être utilisés comme des attributs de la DataFrame. Pratique (qu’on n’attend pas).

L’une des forces de Pandas est de nous proposer tout un tas de solutions pour répondre à des questions existentielles tel que “quel est l’âge moyen par genre et par latéralité?”. Comme en SQL où la réponse sortirait du fondement d’une clause GROUP BY et d’une fonction d’agrégation, il en va de même ici :

In [25]: df.groupby(['Genre','Lateral']).aggregate(np.mean)
Out[25]: 
                     Age
Genre Lateral           
femme droite   45.476190
      gauche   49.208333
homme droite   41.571429
      gauche   55.823529
 
[4 rows x 1 columns]

OMG! c’est quoi c’t'index de malade? Un MultiIndex jeune padawan, qui te permettra d’organiser tes données par catégorie/niveau, et d’y accèder par le paramètre level dans pas mal de fonctions, mais ça je te laisse le découvrir par toi-même. Je ne vais pas non plus m’étendre plus sur toutes les possibilités offertes par les DataFrame, il y a tellement à dire qu’il faudrait plusieurs articles pour en faire le tour. Juste conclusionner sur la facilité d’intégration Pandas/matplotlib en vous disant que les Series et DataFrame ont une fonction plot permettant directement de visualiser les données, et ça, c’est juste jouissif.

Datetime dans les index

Je vous avez dit qu’on reviendrait sur les indexes, et là c’est pour rentrer dans le lourd (mais non pas toi Carlos). Pandas donc supporte l’indexation sur les dates, en reprenant et en élargissant les possibilités offertes par feu le module scikits.timeseries.
Prenons l’exemple de données (complètement bidons) fournies par un capteur à intervalle régulier sur un pas de temps horaire:

In [26]: dtindex=pd.date_range(start='2014-04-28 00:00', periods=96, freq='H')
 
In [27]: data=np.random.random_sample(96)*50
 
In [28]: df=pd.DataFrame(data, index=dtindex, columns=['mesure'])
 
In [29]: df.head()
Out[29]: 
                        mesure
2014-04-28 00:00:00  49.253929
2014-04-28 01:00:00   1.910280
2014-04-28 02:00:00   7.534761
2014-04-28 03:00:00  39.416415
2014-04-28 04:00:00  44.213409
 
[5 rows x 1 columns]
 
In [30]: df.tail()
Out[30]: 
                        mesure
2014-05-01 19:00:00  25.291453
2014-05-01 20:00:00  26.520291
2014-05-01 21:00:00  33.459766
2014-05-01 22:00:00  44.521813
2014-05-01 23:00:00  28.486003
 
[5 rows x 1 columns]

dtindex est un DatetimeIndex initialisé au 28 avril 2014 à 0 heure comportant 96 périodes de fréquence horaire, soit 4 jours. La fonction date_range peut aussi prendre en arguments des objets datetime purs au lieu de chaine de caractère (manquerait plus que ça…), et le nombre de périodes peut être remplacé par une date de fin.
Si l’on veut calculer, disons le maximum (horaire) par jour, rien de plus simple, il suffit de “resampler” en données journalières (‘D’ pour Day) et de dire comment aggréger le tout:

In [31]: df.resample('D', how=np.max)
Out[31]: 
               mesure
2014-04-28  26.298282
2014-04-29  28.385418
2014-04-30  26.723353
2014-05-01  24.106092
 
[4 rows x 1 columns]

Mais on peut aussi convertir en données quart-horaire (upsampling) en remplissant les données manquantes par celles de l’heure fixe:

In [32]:  df[:3].resample('15min', fill_method='ffill')
Out[32]: 
                        mesure
2014-04-28 00:00:00  49.253929
2014-04-28 00:15:00  49.253929
2014-04-28 00:30:00  49.253929
2014-04-28 00:45:00  49.253929
2014-04-28 01:00:00   1.910280
2014-04-28 01:15:00   1.910280
2014-04-28 01:30:00   1.910280
2014-04-28 01:45:00   1.910280
2014-04-28 02:00:00   7.534761
 
[9 rows x 1 columns]

Cependant, Pandas propose aussi d’autres possibilités non dépendantes des DatetimeIndex mais qu’il est bon de connaître, notamment celle pour remplacer les données manquantes avec fillna ou celle pour interpoler entre les données valides avec interpolate

In [52]:  df[:3].resample('15min')
Out[52]: 
                        mesure
2014-04-28 00:00:00  49.253929
2014-04-28 00:15:00        NaN
2014-04-28 00:30:00        NaN
2014-04-28 00:45:00        NaN
2014-04-28 01:00:00   1.910280
2014-04-28 01:15:00        NaN
2014-04-28 01:30:00        NaN
2014-04-28 01:45:00        NaN
2014-04-28 02:00:00   7.534761
 
[9 rows x 1 columns]
 
In [53]:  df[:3].resample('15min').fillna(df.mean())
Out[53]: 
                        mesure
2014-04-28 00:00:00  49.253929
2014-04-28 00:15:00  26.378286
2014-04-28 00:30:00  26.378286
2014-04-28 00:45:00  26.378286
2014-04-28 01:00:00   1.910280
2014-04-28 01:15:00  26.378286
2014-04-28 01:30:00  26.378286
2014-04-28 01:45:00  26.378286
2014-04-28 02:00:00   7.534761
 
[9 rows x 1 columns]
 
In [54]:  df[:3].resample('15min').interpolate()
Out[54]: 
                        mesure
2014-04-28 00:00:00  49.253929
2014-04-28 00:15:00  37.418016
2014-04-28 00:30:00  25.582104
2014-04-28 00:45:00  13.746192
2014-04-28 01:00:00   1.910280
2014-04-28 01:15:00   3.316400
2014-04-28 01:30:00   4.722520
2014-04-28 01:45:00   6.128641
2014-04-28 02:00:00   7.534761
 
[9 rows x 1 columns]

Voilà, j’espère que vous aurez plaisir à travailler avec cette librairie, il manquait vraiment un outil de cette trempe en Python pour l’analyse de données et je pense qu’on n’a plus trop grand chose à envier maintenant par rapport à des langages spécilisés. Je n’ai pas parlé de Panel qui est le passage à la troisième dimension, ni des possibilités d’export, notamment la df.to_html que je vous laisse le soin de découvrir.

A plus, et amusez vous bien avec votre bambou.

\o/

flattr this!

………………………………………… Arg

vendredi 9 mai 2014 à 12:11

Je suis en train de rendre visite à Max. Il va bien, il a toutes ses dents, la truffe humide et le poil soyeux.

Par contre :

⟩ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=36 time=384 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=36 time=1134 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=36 time=1351 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=36 time=873 ms
64 bytes from 8.8.8.8: icmp_seq=6 ttl=36 time=1258 ms
64 bytes from 8.8.8.8: icmp_seq=7 ttl=36 time=1299 ms
64 bytes from 8.8.8.8: icmp_seq=8 ttl=36 time=1431 ms
64 bytes from 8.8.8.8: icmp_seq=9 ttl=36 time=1461 ms
64 bytes from 8.8.8.8: icmp_seq=10 ttl=36 time=1474 ms
64 bytes from 8.8.8.8: icmp_seq=11 ttl=36 time=1178 ms
64 bytes from 8.8.8.8: icmp_seq=12 ttl=36 time=1932 ms
64 bytes from 8.8.8.8: icmp_seq=13 ttl=36 time=2023 ms
64 bytes from 8.8.8.8: icmp_seq=14 ttl=36 time=1818 ms
64 bytes from 8.8.8.8: icmp_seq=15 ttl=36 time=1546 ms
64 bytes from 8.8.8.8: icmp_seq=16 ttl=36 time=1188 ms
64 bytes from 8.8.8.8: icmp_seq=17 ttl=36 time=1110 ms
64 bytes from 8.8.8.8: icmp_seq=18 ttl=36 time=998 ms
^C
--- 8.8.8.8 ping statistics ---

Et je vous raconte pas comme c’est chiant avec WordPress.

flattr this!

Quelle est la différence entre un bug et un virus ?

mercredi 7 mai 2014 à 15:25

Article ultra débutant, mais hey, encore un truc très peu expliqué sur Internet pour l’excuse bidon que “c’est évident”.

Un virus, c’est un programme malveillant

Il a été conçu dans le but de nuire en utilisant la machine qu’il infecte. C’est donc un logiciel en plus sur votre machine, et qui pose des problèmes. Attention, un virus ne va pas forcément ralentir votre ordinateur ou le faire planter. Les virus modernes vont justement, en général, essayer de garder votre ordinateur en bon état (parfois en désinstallant d’autres virus !), afin d’avoir confortablement l’usage de votre machine.

Le virus entre dans la catégorie des programmes dits “malwares”, c’est à dire des logiciels nuisibles. Mais il n’est pas le seul, il y en a un paquet d’autres qui ne sont pas des virus : spywares (logiciels qui vous espionnent), adwares (logiciels qui vous affichent de la publicité tout le temps), ransomwares (logiciels qui prennent vos données en otage). Ce sont tous des malwares, c’est à dire des programmes nuisibles, mais pas des virus.

Généralement un virus a pour but de prendre le contrôle de votre machine, soit pour vous voler des données, soit pour se propager, soit pour l’utiliser comme machine zombie. Dans ce dernier cas, votre machine servira à un pirate qui pourra l’utiliser pour attaquer d’autres machines, envoyer du spam avec ou simplement vendre sa puissance sur Internet.

Ne pensez jamais que votre machine n’est “pas intéressante” pour les pirates sous prétexte que vous ne faites rien de particulier avec votre ordinateur. À partir du moment où votre ordinateur est connecté à Internet, il est intéressant, il peut rapporter de l’argent de bien des façons à un attaquant, même sans que l’argent vienne (directement) de vous.

Pour se protéger des virus, il faut avoir TOUS ses logiciels à jour, mais aussi éviter d’utiliser des systèmes trop sensibles aux virus. Si vous devez utiliser l’un d’entre eux (par exemple Windows), il faut rajouter un antivirus ET un firewall, même si vous ne faites qu’afficher des pages web sur des sites de confiance.

Conficker est un virus.

Un bug, c’est une erreur humaine

Un bug n’est pas un programme en plus, c’est une erreur de conception qui existe dans un des programmes qui est déjà sur votre machine.

Les machines sont stupides, elles ne font que ce qu’on leur dit. Quand vous voyez une application fonctionner, cela n’est que le résultat de millions d’instructions écrites à la main par les hommes qui ont créé vos logiciels, et ces hommes sont faillibles. Parfois, ils font une erreur dans le programme, et cette erreur peut avoir tout un cas de conséquences inattendues : le programme ne fait pas ce que vous voulez, il le fait mais mal, il est lent, il plante, etc.

Tout, absolument TOUT sur votre machine, est un programme. Et TOUT peut contenir un bug. En fait, aujourd’hui les systèmes informatiques sont tellement complexes qu’il y a forcément des bugs sur votre machine. Mais souvent ce sont des bugs discrets, qui ne sont pas très graves.

Dites-vous qu’un téléphone ou une tablette, si cela vous parait simple à utiliser, est bien plus complexe qu’un avion ou une fusée dans son fonctionnement en détail. Pas parce que c’est techniquement plus poussé, mais parce qu’il y a tellement de couches et de parties qui interagissent entre elles. Et dans ce gros fouillis il y a des erreurs, les fameux bugs.

On peut difficilement se protéger des bugs. Garder vos logiciels à jour peut aider à corriger les bugs précédents, mais parfois en ajouter des nouveaux. Les bugs font partie de la vie, aucun système n’est parfait. En revanche, plus un système est simple et maitrisé, moins il a de chance de contenir de bug. Si les bugs vous font peur, choisir un produit qui ne fait qu’une seule chose, mais bien, ou choisir un produit éprouvé, vous permet d’espérer une expérience avec moins de bugs.

Heartbleed est un bug.

Subtilités

Un virus utilise souvent un bug pour attaquer votre système. Le virus a en effet un objectif (au moins celui de se reproduire), et le logiciel qu’il attaque n’est généralement pas conçu pour lui permettre de l’atteindre. Le virus va donc souvent utiliser un bug du système pour obtenir ce qu’il veut.

A l’inverse, un bug n’a pas d’objectif, c’est une erreur, et donc il ne peut pas “causer un virus”. Ça ne veut rien dire.

Généralement, tout ce petit monde va donc ensemble, un virus peut exploiter un bug, dans le but d’installer un adware sur votre machine, afin de gagner de l’argent via la publicité, un keylogger pour récupérer votre numéro de carte bleue et un rootkit pour garder votre machine sous contrôle. Il y a donc 5 choses ici : le virus, le bug, l’adware, le spyware et le rootkit. Ce sont 5 choses différentes, mais la raison pour laquelle vous en entendez souvent parler en même temps, c’est qu’elles sont liées.

Mythes

Mon ordinateur n’a pas de bug

C’est impossible. C’est comme dire qu’il n’y a pas de fourmis dans vote jardin. Ce qui est possible, c’est qu’un bug ne vous gène pas et que vous n’en ayez vu aucun.

Je ne peux pas attraper de virus, parce que je ne fais rien de dangereux

Vous n’avez aucune idée de ce qui est dangereux. Croyez-moi, si auparavant vous ne saviez pas la différence entre un bug et un virus, vous n’avez pas la compétence (ce n’est pas une insulte) pour savoir ce qui met en danger votre machine. Et donc, vous le faites.

Mon ordinateur tourne bien, je n’ai pas de virus

Les virus modernes essayent le plus souvent d’être discrets et de ne pas vous causer de souci pour éviter que vous ayez envie de les supprimer.

Mon ordinateur affiche plein de pubs, j’ai un virus

Il y a des tas d’autres malwares qui causent cela. Il y a très peu de chance que ce soit un virus. Ça ne veut pas dire qu’il ne faut pas traiter votre ordinateur, mais un anti-virus ne suffira pas. Il vous faut des programmes anti-malwares plus généralistes.

flattr this!

Cet article est trop gay

samedi 3 mai 2014 à 15:44

Je fréquente plus de LBG que la moyenne. Encore plus cette année, puisque deux de mes colocs ne sont pas hétéros, donc forcément avec les amis d’amis, ça charge mes statistiques.

Du coup, j’ai l’occasion de vivre du gay quotidien, et pas juste en soirée, fiesta ou autre événement. Bref, en mode caleçon, bière, pizza, film, sport en plein air et achat de pomme de terre.

Comme toujours, les minorités se tapent leurs lots de stéréotypes, que je peux confronter à mon petit échantillon non représentatif.

Plus d’activité sexuelle

C’est biaisé. Ce n’est pas vrai pour la majorité.

Répartition du nombre de personnes par nombre de partenaires sexuels et orientation sexuelle

Piqué à l'article linké plus haut

Par contre, c’est vrai que dans mon entourage, proportionnellement, un plus gros pourcentage de gays ont une vie sexuelle très active que parmi les hétéros. Je ne vais pas m’aventurer sur une explication du pourquoi, mais c’est un constat, que ce soit pour les filles et les mecs. D’ailleurs, ce sont les plus à l’aise pour en parler, même si généralement chez nous, ça parle de cul de toute façon et que j’ai des amis franchement délurés (sado-masos, partouseurs, stripteasers, etc). Finalement je suis super classique comme mec comparé à mes fréquentations.

Les homos essayent de convertir les hétéros

Non, mais par contre ils les draguent. Et certains font régulièrement des tentatives malgré un “non” explicite précédent. Ce n’est pas méchant, c’est parfois relou, mais envoyer chier un boulet collant est de bonne guerre pour tous les sexes. En prime, ça vous permet de vous mettre à la place des nanas qui se font draguer par des boulets.

Dans tous les cas, ils essayent, car parfois ça marche. La théorie d’un de mes potes c’est “un hétéro bourré est un hétéro suçable”. Il a par ailleurs rencontré son petit ami actuel en le pompant dans ma cuisine lors d’une soirée, ce qui fait qu’on a pas pu accéder aux petits fours pendant quelques temps.

Dessin de batman enculant Robin

Dans certains comics, Robin à 10 ans...

Même parmi ceux qui ne tentent pas, ils en a qui sont juste naturellement très tactiles, et si on est pas à l’aise avec le fait de faire calin-calin avec un gayzounours velus (les miens sont italienne et espagnol…), ça peut mettre mal à l’aise. Ca n’a rien à voir avec le côté homo/hétéro, c’est chiant y compris avec des straights.

Ce qui est important c’est d’être très simple et direct : oui ou non. Ici est la limite. Pour certain, la limite c’est “tu m’approches pas à moins de 2 m”, pour d’autre, c’est “ok pour le bisou sur la joue”. On s’en fout, tout est acceptable. Mais il faut le dire, et ne pas ruminer dans son coin, c’est idiot. Votre virilité/féminité n’est pas en jeu, votre confort, oui.

Qu’on se le dise, vous ne tomberez pas sur un gang bang surprise, et comme tout le monde, il y a les introvertis et les extravertis, donc ne pas partir sur une idée reçue. Les filles sont moins rentre dedans que les garçons en milieu mixte, par contre en boîte, tout est permis. C’est un peu le but.

On me signale dans la gayreillette : “nan mais moi je fais pas ça”. C’est vrai. Lui il fait pas ça. Vous voulez dire que les gays peuvent être des gens ordinnaires et classiques ? Noooooon ? Surpris ?

Les gays ont de l’argent

Encore une fois pas forcément, mais la majorité que je connais vivent bien. Genre, bien, bien. Mon pote qui lit l’article est en train de me dire “bon, ben tu me fileras mon chèque de gay alors, je l’attends toujours”. Mais il est de mauvaise foi, il vit avec moi dans un 200m2 avec 1000m2 de jardin. A 10m du tram, en ville. Y a pire.

En même temps, quand on a pas d’enfant à 30 ans, c’est généralement plus facile. Après j’ai une amie lesbienne qui galère tout le temps, elle est prof et elle roule à vélo, faut pas déconner, il n’y a pas un fond de financement secret des gays dont la mission est de les maintenir dans un état d’opulence. C’est pas con comme idée ça, je vais breveter.

Gir animé du film zombiland montrant un personnage essuyant ses larmes avec des billets

MRW I'm single with no children

Les gays sont sociables

J’ai envie de dire, pas plus que les autres. Mais en réfléchissant deux secondes, j’ai un couple qui est toujours fourré en soirée, un lesbienne qui est la fille la plus caline du monde, deux colocs qui font des soirées toutes les semaines, occasionnellement à 200 invités… Alors je vais rien dire… C’est peut être une coincidence…

Dessin de bisounours mangeant un humain

Ce qu'on fait vraiment dans les soirées à la maison

Les homosexuels sont des folles

Je n’en ai rencontré qu’un dans ma vie, donc c’est plutôt rare. Oui il y a des trais parfois particuliers, mais pas nécessairement le côté éphéminé pour les mecs ou camioneur pour les nanas. J’ai un très mauvais gaydar donc je ne saurais pas vous faire une liste, cela dit. Un gay n’est pas forcément artiste, honête, joyeux, fêtard, ou autre. Par contre, je note que tous ont une forme de sensibilité plus assumée. Bon, je note, je note, sur ceux que je connais, hein. Je note ce que je peux noter.

Le truc c’est que quand un gay est discret, vous ne saurez juste jamais qu’il l’est. C’est pas écrit sur sa tronche. Il y a les timides, ceux qui ne s’assument pas, ceux qui font comme tout le monde, etc.

Comprenez en tout cas, que la gay pride, c’est juste un événement festif, ce n’est pas représentatif d’un mode de vie. La fistinière non plus. Ca ne veut pas dire que ça ne peut pas l’être, évidement, mais perso notre dernière activité mixte, c’était une partie de magic bi VS lesbienne vs hétéro. Pas un défilé de cuir.

Affiche de la série "the new normal"

Je trouve génial que quand les médias essayent de rendre quelque chose ordinaire, ils le rendent tout de suite caricatural

Les bis aiment autant les mecs que les filles

Généralement, bien qu’ils puissent avoir des aventures avec les deux, il y a toujours un sexe qui prédomine. Il n’y a pas de régle, car il y autant de degré de biitude qu’il y a de bis, mais quand on aime la vanille et le chocolat, on a souvent une préférence pour un parfum, particulièrement pour les relations à long terme. Ce n’est pas forcément ce qu’ils vous diront, mais ça se voit dans les stats de dating, comme ont dit dans les milieux autorisés.

Si on essaye dresser un profile type, on va se planter dans tous les cas. On a aussi les asexuels, les asexués, les trans opérés, les trans non opérés, et je soupçonne un de mes amis d’aimer beaucoup son chien…

Ils / elles ont envie de me baiser

C’est possible. Moi y a plein de nana que j’ai envie de baiser.

Fille à gros seins et godzilla

Moi non plus

L’inverse est aussi tout à fait courant : aimer quelqu’un sans avoir envie de le baiser. Wow. Shoker.

Ils / elles ont le sida

Meh.

Le logo SEGA parodié en SIDA

Le sida, communément représenté par une boule pleine de pique qui court et ramasse des anneaux. Heu...

Ce sont des drogués

Beaucoup de mes amis consomment au moins une drogue (au minimum clope ou alcool), parfois 2/3 voir 4. Personnellement je ne fume pas et bois peu. Mais il n’y aucune différence entre les homos et les hétéros. C’est tout pareil.

flattr this!

La martingale à la roulette en Python

jeudi 1 mai 2014 à 12:17

Sur internet, c’est bien connu, on peut perdre du poids, trouver une fille facile près de chez soit, et gagner beaucoup d’argent rapidement et sans risque.

Une de ces techniques qu’on vous vend est la fameuse martingale, mais appliquée aux casinos en ligne. Outre le fait que vous ne pouvez pas vous fier à un serveur distant pour ne pas tricher, les jeux de hasard sont de toute façon toujours en faveur de la banque.

Nous allons nous intéresser à la martingale la plus simple, celle appliquée à la roulette. Quand j’étais à l’université, entre deux parties de Munchkins, nous cherchions un moyen de faire du pognon. Et on a failli s’organiser une session au casino de notre ville pour appliquer la technique suivante :

  1. Jouer une petite mise sur une couleur;
  2. Si on perd, revenir en 1 mais avec une mise équivalent au double de ses pertes.
  3. Si on gagne, encaisser, retourner en 1, mais avec la toute petite mise de départ.

L’idée était que si tu perdais, tu doublais ta mise jusqu’à ce que ça te rembourse tes pertes. Sinon, tu gagnes, et tu empoches. Seulement voilà, la roulette à la couleur, ce n’est pas 50% de chance, car il y a le zéro, qui n’est ni rouge, ni noir.

Comme on était des petits cons nuls en probas, mais des petits cons programmeurs, on avait simulé le jeu avec un programme Python, juste au cas où :

import random
 
# Une roulette (en France), c'est un 0 vert, et des numéros de
# 1 à 36 alternativement rouges et noirs.
roulette = ["green"]
roulette.extend("red" for i in range(1, 37, 2))
roulette.extend("black" for i in range(2, 37, 2))
 
# Regardons ce que donne la proba de choper le rouge avec le générateur
# de nombre pseudo-aléatoires de Python.
count = 0
for i in range(100000):
    count += random.choice(roulette) == "red"
print("Average chance of picking red: %s" % (count / 100000 * 100))
 
# Time to play ! Insérer ici la musique d'un film américain ambiance Las Vegas.
def play(rounds, budget=10000, color="red", start_bet=5):
    initial_budget = budget
    max_bet = start_bet
    bet = start_bet
    loss = 0
    # On limite le nombre de paris
    for round in range(rounds):
        # On mise
        budget -= bet
        if random.choice(roulette) != color:
            # On a perdu, on mise le double de ses pertes.
            loss += bet
            bet = loss * 2
            # Si jamais c'est plus que notre pognon, on se couche et on chiale.
            if bet > budget:
                break
            # On garde une trace de notre mise max pour évaluer le budget max.
            if (max_bet < bet):
                max_bet = bet
        else:
            # Si on gagne, on récupère notre mise et le gain, et on recommence.
            budget += bet * 2
            bet = start_bet
            loss = 0
 
    return budget - initial_budget, max_bet
 
print("10 rounds | balance: %s (max=%s)" % play(10))
print("100 rounds | balance: %s (max=%s)" % play(100))
print("1000 rounds | balance: %s (max=%s)" % play(1000))
print("10000 rounds | balance: %s (max=%s)" % play(1000))

Là le budget est large, mais nous on avait 800 euros… Bref, le résultat :

$ python3 roulette.py
Average chance of picking red: 48.78
10 rounds | balance: 10 (max=90)
100 rounds | balance: 1835 (max=2430)
1000 rounds | balance: -3585 (max=2430)
10000 rounds | balance: -3495 (max=2430)
 
$ python3 roulette.py
Average chance of picking red: 48.67
10 rounds | balance: 15 (max=30)
100 rounds | balance: -3620 (max=2430)
1000 rounds | balance: -3180 (max=2430)
10000 rounds | balance: -4670 (max=7290)
 
$ python3 roulette.py
Average chance of picking red: 48.507
10 rounds | balance: 45 (max=90)
100 rounds | balance: 1800 (max=2430)
1000 rounds | balance: -3370 (max=2430)
10000 rounds | balance: -3455 (max=2430)
 
$ python3 roulette.py
Average chance of picking red: 48.4
10 rounds | balance: 50 (max=30)
100 rounds | balance: 1940 (max=2430)
1000 rounds | balance: 1435 (max=7290)
10000 rounds | balance: -970 (max=7290)
 
$ python3 roulette.py
Average chance of picking red: 48.853
10 rounds | balance: -115 (max=270)
100 rounds | balance: -3535 (max=2430)
1000 rounds | balance: -2100 (max=7290)
10000 rounds | balance: -2120 (max=7290)

C’est pas vraiment la fortune assurée et en prime, dès qu’on veut jouer un peu sérieusement, il faut un budget max énorme. Mais surtout, il y a une grosse contrainte de temps, puisque 10 rounds c’est une bonne heure de jeu dans un casino réel.


Télécharger le code de l’article.

flattr this!