Skip to main content

Poker Analysis using Python (numpy and pandas)

In this I did an analysis on poker. I made my own dataset by randomly selecting 7 cards from the dataset. It does not gives the actual results. It is more of a simulation of actual data.


I have used jupyter-notebook for this you can use any IDE according to your liking.

Start by importing the modules.

import pandas as pd
import numpy as np
import random
import time


Then I created a function calculate_hand which takes hand as a list and returns a boolean list with the corresponding values [royal_flush, straight_flush, four_of_a_kind, full_house, flush, straight, three_of_a_kind, two_pairs, pair, highcard]. If the hand has three cards of same value three_of_a_kind will be True, also pair will be True because if a hand has three of a kind, it also has a pair. Highcard always return the high card.

ALL_CARDS_NUM = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14}
ALL_CARDS_NUM_TO_TEXT = {1:'A', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10:'T', 11:'J', 12:'Q', 13:'K', 14:'A'}
FACE_CARDS = {'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14}

def to_number(card):
    if card[0].isnumeric():
        return int(card[0])
    else:
        return FACE_CARDS[card[0]]
   
   
def is_straight(num):
    all_straights = []
    seqcount = np.zeros(7, dtype=np.int)
   
    for i in range(1,len(num)):
        if ALL_CARDS_NUM[num[i-1]] - ALL_CARDS_NUM[num[i]] == -1:
            seqcount[i] = seqcount[i-1] + 1 
        elif ALL_CARDS_NUM[num[i-1]] == ALL_CARDS_NUM[num[i]]:
            seqcount[i] = seqcount[i-1]

    for x in np.argwhere(seqcount >= 4):
        return (True, seqcount)
   
    try:
        if num[-1] == 'A' and seqcount[num.index('5')] >=3:
            return (True, seqcount)
    except:
        pass
   
    return (False, seqcount)


def count_cards(num):
    ptf = {}
    temp_count = np.zeros(13)
   
    for x in num:
        temp_count[ALL_CARDS_NUM[x]%13 - 1] += 1
   
    for x in np.argwhere(temp_count > 1):
        ptf[ALL_CARDS_NUM_TO_TEXT[x[0] + 1]] = int(temp_count[x[0]])
       
    return ptf

def count_suites(suite):
    suites_array = {'S': [],
                   'C': [],
                   'H': [],
                   'D': []}
       
    for i in range(len(suite)):
        suites_array[suite[i]].append(i)

    for key, value in suites_array.items():
        if len(value) >= 5:
            return value

    return []

def calculate_hand(temp_hand, show = False):
    hand = temp_hand.copy()
    hand.sort(key=to_number)
    num = []
    suite = []
   
    hand_value = {}
   
    for x in hand:       
        num.append(x[0])
        suite.append(x[1])
   
   
   
    #straight
    straight, seq = is_straight(num)
    pairs = count_cards(num)
    flushes = count_suites(suite)
   
    #straignt flush
    straight_flush = False
    straight_flush_sequence = []
   
    if straight and flushes:
        for i in range(len(flushes)-4):
            flush_seq = [num[z] for z in flushes[i:i+5]]
            temp, _ = is_straight(flush_seq)
           
            if temp:
                straight_flush = True
                straight_flush_sequence = flush_seq
   
    #royal flush
    royal_flush = False
   
    if straight_flush:
        if straight_flush_sequence[-1] == 'A':
            royal_flush = True
       
    #pairs
    pair_value = np.asarray([value for _,value in pairs.items()], dtype=np.int)

    #four of a kind
    four_of_a_kind = False
    if np.argwhere(pair_value >= 4).size != 0:
        four_of_a_kind = True
       
   
    #three of a kind
    three_of_a_kind = False
    if np.argwhere(pair_value >= 3).size != 0:
        three_of_a_kind = True

   
    #full house
    full_house = False
    if three_of_a_kind and np.argwhere(pair_value >= 2).size >= 2:
        full_house = True
       
    #flush
    flush = False
    if flushes:
        flush = True
   
    #two pairs
    two_pairs = False
   
    if np.argwhere(pair_value >= 2).size >= 2:
        two_pairs = True
       
    #pairs
    pair = bool(pairs)
   
    #high card
    highcard = num[-1]

    if show:
        print(num, suite)
        print("royal flush:\t\t",royal_flush)
        print("straight flush:\t\t", straight_flush)
        print("four of a kind:\t\t", four_of_a_kind)
        print("full house:\t\t", full_house)
        print("flush:\t\t\t", flush)
        print("straight:\t\t", straight)
        print("three of a kind:\t", three_of_a_kind)
        print("Two pairs:\t\t", two_pairs)
        print("Pair:\t\t\t", pair)
        print("High card: \t\t",highcard)
   
   
    return [royal_flush, straight_flush, four_of_a_kind, full_house, flush, straight, three_of_a_kind, two_pairs, pair, highcard]


The other functions here are the helping functions.

Now you can create your dataset:

card_num = ['A','2','3','4','5','6','7','8','9','T','J','Q','K']
suite = ['S','C','H','D']
main = []

def randCard():
    choosen_num = random.choice(card_num)
    choosen_suite = random.choice(suite)
   
    return str(choosen_num) + choosen_suite

start = time.time()

for i in range(1000000):
    temp = []
    for j in range(7):

        choosen_card = randCard()

        while (choosen_card in temp):
            choosen_card = randCard()

        temp.append(choosen_card)
       
    hand_val = calculate_hand(temp)
   
    try:
        top_val = hand_val.index(True)
    except:
        top_val = 9
   
    temp += hand_val
    temp.append(top_val)
   
    if i%100000 == 0:
        print("Time Elapsed",i,"=", time.time() - start)
   
    main.append(temp)

print("\n\nTotal Time Elapsed =", time.time() - start) 


The dataset is stored in the main variable now convert into a pandas dataframe.

x = pd.DataFrame(data=main, columns=["YC1", "YC2", "F1", "F2", "F3", "R", "T", "royal_flush", "straight_flush", "four_of_a_kind", "full_house", "flush", "straight", "three_of_a_kind", "two_pairs", "pair", "highcard", "top_val" ])

x.head()


Now you can either save your data set in csv format or create new dataset every time you decide to use this.

x.to_csv(file_name,index=False)
 
To read the csv file you can use read_csv function
 
x = pd.read_csv(file_name) 

Now we can start analysing the data. 
 
top_hand_value_dict = {
    0: "royal_flush", 
    1: "straight_flush", 
    2: "four_of_a_kind", 
    3: "full_house", 
    4: "flush", 
    5: "straight",
    6: "three_of_a_kind", 
    7: "two_pairs", 
    8: "pair", 
    9: "highcard" 
}

def calculate_hand_value(data, x1, x2):
    
    print("\nIndividuaized values\n")
    hands = data.loc[((data["YC1"] == x1) & (data["YC2"] == x2)) | ((data["YC1"] == x2) & (data["YC2"] == x1))]
    len_hand = len(hands)
    
    print("Length of the sample: ", len_hand, "\n")

    
    for i in range(9):
        perc_val = 100 * hands[top_hand_value_dict[i]].sum()/len_hand
        print(top_hand_value_dict[i] + ":\t", round( perc_val , 3))
    
    z = hands.loc[:, hands.columns[7:len(hands.columns)-1]].sum(axis = 1)
    print("\nNothing:\t\t" , 100 * len(z.loc[z == 0])/len(z) )
        
def calculate_top_values(data, x1, x2):
    
    print("\nTop Values:\n")
    hands = data.loc[((data["YC1"] == x1) & (data["YC2"] == x2)) | ((data["YC1"] == x2) & (data["YC2"] == x1))]
    len_hand = len(hands)
    
    print("Total number of rows:", len_hand)
    
    l = hands['top_val'].value_counts()
    
    for key, value in dict(l).items():
        print(top_hand_value_dict[key] + ":\t", round( (value/len_hand)*100, 3))
     
calculate_hand_value check the possibility of the value of the hand. x1 and x2 are the cards. 
calculate_top_values check the top value of the hand. x1 and x2 are the cards. 
calculate_hand_value(x, "8S", "8D")
calculate_top_values(x, "QH", "JS")

Use above functions to check outputs.
 
def hand_losing(data, YC1, YC2, delt_card):
    
    print("\nChances of loosing this hand: ")
    
    hand = [YC1, YC2] + delt_card
    
    len_delt_card = len(delt_card)
        
    delt_card_hands = data.loc[ data.iloc[:,0:7].isin(delt_card).sum(axis="columns") >= len_delt_card]

    if delt_card_hands.empty:
        print("Sorry no values present!!! Increase the rows database")
    else:
        
        len_hand = len(delt_card_hands)
    
        hand_val = calculate_hand(hand)

        try:
            top_val = hand_val.index(True)
        except:
            top_val = 9
            
        len_lost =  len(delt_card_hands.loc[data['top_val'] < top_val])
        print("Chances of losing by cards value: ", len_lost)
        
        hand_high_card = ALL_CARDS_NUM[hand_val[9]]

        len_lost_high_val = len(
            delt_card_hands.loc[
                (data['top_val'] == top_val) &
                (data['highcard'].apply(lambda i: ALL_CARDS_NUM[i]) > hand_high_card)
            ]
        )
        
        print("Chances of losing by highcard: ", len_lost_high_val)
        
        unpredicted = len(
            delt_card_hands.loc[
                (data['top_val'] == top_val) &
                (data['highcard'] == hand_val[9])
            ]
        )
        
        print("Unpredicted data: ", unpredicted)
        
        
        print("Chances of losing (w unpredicted): ",
              len_lost + len_lost_high_val, "/",len_hand)
        print("Percentage of losing (w unpredicted): ", 
              round(100 * (len_lost + len_lost_high_val)/len_hand,3))
        
        print("Chances of losing (w/o unpredicted): ", 
              len_lost + len_lost_high_val, "/",(len_hand - unpredicted))
        print("Percentage of losing (w/o unpredicted): ", 
              round(100 * (len_lost + len_lost_high_val)/(len_hand - unpredicted),3))
hand_losing gives the number of times your hand can loose given the dataset.
 
hand_losing(x, "8S", "8D", ["8C", "TS", "TH", "9S", "8H"])
 
You can change the number of cards in the list for turn,flop and river.
 
Hope you liked this. 
 

Comments

Popular posts from this blog

Social Influence: Some tips and tricks

In our previous posts, we have learnt about some of the techniques in Social Psychology. Now in this post I want to tell you about some techniques that you can use in real life to influence people or to protect yourself from being influence by other people and make rash decisions. Some of the tips are: People more likely to help you when you ask them to imagine or predict doing something. Telling some stranger your name first can also be helpful when asking a favour. One can say “Hello, I am ___ and I was wondering whether you do me a favour.” Talking with people is more helpful that talking at people when asking for something/favour. Engaging people in dialogues rather than a monologue. Now I would like to tell you about the most commonly used persuasion techniques. These techniques are: 1.       Foot-in-the-door technique 2.       Door-in-the-face technique 3.       Low-ball technique N...

Science of Persuation: How to persuade others?

According to wikipedia.org, Persuasion is: Persuasion is an umbrella term of influence . Persuasion can attempt to influence a person's beliefs , attitudes , intentions , motivations , or behaviors . In other words, persuasion is a process aimed at changing a person's (or a group's) attitude or behaviour toward some event, idea, object, or another person(s). Knowing some of the persuasion techniques can be very helpful for a person as this techniques can help that person to excel in life (and/or his respective field like business, study, and even relationships). So let's begin by asking these three questions and then I will tell you about Robert Cialdini 's 6 principles of persuasion. So the questions are: Should one use counter-arguments while persuading? Should you take the central route (or peripheral route) to persuasion? Should you scare the receiver of the persuasion? Answering these questions, counter-arguments can be helpful at times w...