본문 바로가기

무료 로또 번호

로또 번호 예측 프로그램 만들기 (파이썬 무료 코드 제공)

반응형

안녕하세요.

그동안 제가 직접 만든 프로그램으로 매 회차 무료 로또 번호를 뽑아드렸습니다.

이번 게시물은 해당 프로그램에 대해 설명하는 시간으로 제가 선택한 통계학과 알고리즘을 하나하나 알려드리겠습니다.

 

1. 기본 가설

일단 프로그램을 만들기 전에 가설을 하나 세워야 합니다.

그 이유는 가설이 없다면 로또 프로그램은 단지, 1~45개의 공에서 랜덤으로 6개의 공을 뽑아주기만 하면 되기 때문입니다.

이러한 이유로 저는 수학적 확률과 경험적 확률에 기반한 가설을 하나 세웠습니다.

https://dhlottery.co.kr/gameResult.do?method=statByNumber

 

로또6/45 당첨통계 - 번호별 통계

* 로또6/45의 당첨번호는 (주)동행복권 공식홈페이지, ARS전화 등을 통해 확인하실 수 있습니다.

dhlottery.co.kr

해당 로또 공식 사이트에서 제공하는 데이터를 보시면

 

 

생각보다 균일하게 숫자를 뽑고 있다는 사실을 확인하실 수 있습니다.

 

이는 수학적 확률이 지켜지는 모습을 보여줍니다.

허나, 실제로 주사위를 던진다고 해서 1~6이 고루고루 나오는 것은 아닙니다.

정말 우연히도 1은 한 번도 안나올 수도 있습니다.

이러한 수학적 확률과 경험적 확률을 적절하게 균형을 맞춰 보는 것이 제 프로그램의 기초 가설이 되겠습니다.

 

2. 가설에 대한 프로그래밍 코드

해당 프로그램은 파이썬을 기반으로 제작하였습니다.

 

1) 각 숫자의 빈도수를 계산

가설을 이용하기 위해서는 각 숫자에 대한 빈도수를 우선적으로 확인해줘야 합니다.

우선, 저는 로또 공식 사이트에서 제공하는 엑셀 파일을 받아왔습니다. 해당 엑셀파일에는 모든 회차의 번호가 존재합니다.

우선, 해당 엑셀 파일을 파이썬으로 불러오는 함수입니다.

# read excel
def read_excel_file(file_path, sheet_name):
    return pd.read_excel(file_path, sheet_name=sheet_name)

 

이제 불러온 엑셀 파일에서 유효한 범위의 데이터를 가져오는 코드입니다.

# 엑셀에서 지정된 범위의 데이터를 추출하는 함수
def get_data_in_range(df, start_cell, end_cell):
    start_row, start_col = start_cell
    end_row, end_col = end_cell
    return df.iloc[start_row-1:end_row, start_col-1:end_col]

 

이후 가져온 엑셀 데이터를 기반으로 빈도수를 계산합니다.

# 숫자 빈도수를 계산하는 함수
def calculate_frequency(data):
    flat_data = data.values.flatten()
    # 숫자만 필터링
    numbers = [x for x in flat_data if isinstance(x, (int, float))]
    return pd.Series(numbers).value_counts()

 

 

 

 

 

2) 이상값 제거 

저의 가설인 수학적 확률과 경험적 확률에 대하여 경험적 확률에 대한 부분입니다.

IQR방식을 이용하였습니다. 

해당 박스플롯과 같이 점으로 표시된 부분은 이상값으로서 유효하지 않은 데이터를 나타냅니다.

이러한 빈도수에 대한 박스플롯에서 너무 적은 빈도수를 갖거나 너무 많은 빈도수를 갖고 있는 데이터들을 이상값으로 하여 유효한 데이터들만 이용해 통계를 추정합니다.

 

경험적 확률에 기반하여 너무 안나오는 숫자들을 배제하고 수학적 확률에 기반하여 너무 많이 나오는 숫자들을 배제하였습니다.

 

아래는 파이썬 코드로 구현한 부분입니다.

# 이상값 제거 함수 (IQR 방법)
def remove_outliers_iqr(frequency_dict):
    values = list(frequency_dict.values())
    q1 = pd.Series(values).quantile(0.25)
    q3 = pd.Series(values).quantile(0.75)
    iqr = q3 - q1
    lower_bound = q1 - 1.5 * iqr
    upper_bound = q3 + 1.5 * iqr
    # IQR 범위 내의 값만 남김
    cleaned_dict = {k: v for k, v in frequency_dict.items() if lower_bound <= v <= upper_bound}
    outliers = {k: v for k, v in frequency_dict.items() if not lower_bound <= v <= upper_bound} #tempo
    return cleaned_dict, outliers

 

 

 

 

 

3) 최빈수 뽑기

위의 방식들을 이용하여 1~ 45개중 6개를 뽑는 방식이 아닌 1~45개중 유효하지 않은 숫자들을 제거하여 경우의 수를 최대한 줄여나갔습니다.

이제는 이를 기반으로 남은 숫자들 중에서 1개를 뽑아보겠습니다.

 

현재 1~45개의 공에서 이상값을 통해 n개의 공을 제거하였다면 45-n개의 공의 남아 있습니다.

이 45-n개의 공중에서 최빈값 3개를 따로 가져와서 3개중에 1개의 공을 랜덤으로 뽑습니다.

이후 이제 남은 공은 45-n-3 C 5 의 조합과정을 하게 되면 됩니다.

 

아래는 코드 구현 방식입니다.

#top3 frequent_ball
def find_top_3_frequent_numbers(frequency_dict):
    sorted_items = sorted(frequency_dict.items(), key=lambda x: x[1], reverse=True)
    return [item[0] for item in sorted_items[:3]]

 

 

 

 

 

 

4) 15주차 미출현 번호 뽑기

로또 공식사이트에는 15주차 미출현 번호인 공에 대해 알려주고 있습니다.

이를 이용하여 15주차 미출현 번호 중 1개의 공을 뽑을 것입니다.

해당 방식을 사용하는 이유는 해당 프로그램의 기초 가설 중 하나인 수학적 확률에 기반하였기 때문입니다.

 

아래는 코드 구현 방식입니다.

우선 15주차 미출현 번호에 대한 배열을 생성합니다.

week15_ball = [5,18,27,29,37,39] #15주차 미출현 번호 배열

 

해당 배열에서 한 개의 공을 랜덤으로 뽑고 결과로 나올 배열에 저장하며, 45-n-3의 경우의 수에서 추가적으로 해당 배열의 숫자들 역시 제거해줍니다.

#15주차 미 출현 공 중 1개를 뽑고 최우선 결과값 result에 저장
    chosen_week15_ball = week15_choice(week15_ball)    
    result_ball.append(chosen_week15_ball)

    
    #15주차 미 출현 공들에 대하여 가중배열에서 삭제처리
    for ball in week15_ball:
        if ball in lucky_ball:
            lucky_ball.remove(ball)

 

 

 

 

 

5) 15주차 가중뽑기

위의 과정을 통하여 뽑아야 하는 공들의 경우의 수를 최대한으로 줄였고, 또한 이미 6개중 2개의 공을 뽑았습니다.

이제 남은 일은 줄여놓은 경우의 수들중 총 4개의 공만 추가적으로 뽑으면 됩니다.

 

4개의 공을 뽑는 방식의 경우 15주차 가중뽑기라는 방식을 사용하여 구현하였습니다.

 

로또 공식사이트에는 아래와 같이 구간별 출현횟수 데이터를 제공합니다.

이를 기반으로 각 구간별 가중치를 설정하여 조작된 랜덤뽑기를 수행합니다.

정확히 말하자면 예를들어 21~25번대 공이 다른 번호대보다 많이 뽑힌다면 해당 번호들의 경우의 수를 높게 설정해준다는 의미입니다.

 

이에 대하여 아래는 코드로 구현한 부분입니다.

 

우선 각 가중치에 대한 변수를 설정합니다.

#구간별 가중치 변수 * 6/13일자 기준
    a_1 = 11 # 1 ~ 5
    a_2 = 12 # 6 ~ 10
    b_1 = 13 # 11 ~ 15
    b_2 = 12 # 16 ~ 20
    c_1 = 10 # 21 ~ 25
    c_2 = 10 # 26 ~ 30
    d_1 = 20 # 31 ~ 35
    d_2 = 7 # 36 ~ 40
    e_1 = 10 # 41 ~ 45

 

이후 저장한 변수들에 대하여 각 번호대의 가중치를 부여하여 경우의 수를 조작해줍니다.

#구간별 출현횟수에 대한 가중치 

    # 1 ~ 5 -> 4
    for i in range(1,6):
        if i in lucky_ball:
            lucky_ball.extend([i] * a_1)

    # 6 ~ 10 -> 4
    for i in range(6,11):
        if i in lucky_ball:
            lucky_ball.extend([i] * a_2)

    # 11 ~ 15 -> 3
    for i in range(11,16):
        if i in lucky_ball:
            lucky_ball.extend([i] * b_1)

    # 16 ~ 20 -> 3
    for i in range(16,21):
        if i in lucky_ball:
            lucky_ball.extend([i] * b_2)

    # 21 ~ 25 -> 5
    for i in range(21,26):
        if i in lucky_ball:
            lucky_ball.extend([i] * c_1)

    # 26 ~ 30 -> 3
    for i in range(26,31):
        if i in lucky_ball:
            lucky_ball.extend([i] * c_2)

    # 31 ~ 35 -> 8
    for i in range(31, 36):
        if i in lucky_ball:
            lucky_ball.extend([i] * d_1)

    # 36 ~ 40 -> 2
    for i in range(36, 41):
        if i in lucky_ball:
            lucky_ball.extend([i] * d_2)

    # 41 ~ 45 -> 3
    for i in range(41, 46):
        if i in lucky_ball:
            lucky_ball.extend([i] * e_1)

 

이제 지정한 경우의 수를 기반으로 4개의 공을 랜덤으로 뽑아줍니다.

#가중치를 이용하여 남은 4개의 공 랜덤 뽑기
    for i in range(4):
        chosen_ball = random.choice(lucky_ball)
        result_ball.append(chosen_ball)

        #slicing을 이용하여 lucky_ball list에서 지정한 값이 아닌 숫자를 제외하고 가져옴
        lucky_ball[:] = (value for value in lucky_ball if value != chosen_ball)

 

 

 

 

저는 위와 같은 방식으로 로또 번호 예측 프로그램을 만들어 제 블로그에 오시는 분들에게 번호를 제공하였습니다.

앞으로도 계속 제공해드릴 예정이며, 또한 조만간 해당 프로그램을 업그레이드 할 계획입니다.

 

코드에 대해 궁금하신것이 있다면 댓글 부탁드립니다.

긴 글 읽어주셔서 감사합니다.

 

반응형