Ở nước tôi, có một trò chơi xổ số hàng tuần trong đó người tham gia chọn 6 số từ dãy 37 và một số khác từ dãy 7. Hãy tập trung vào phần đầu tiên của trò chơi và bỏ qua việc chọn thêm một số từ dãy số 7. 7.
Khi nói đến xổ số có dạng k/N, trong đó k là số lựa chọn mong muốn (trong trường hợp của chúng tôi là 6) trên tổng số N số (trong trường hợp của chúng tôi là 37), một câu hỏi phổ biến là liệu mỗi trong số đó có phải là số không? những con số này có cơ hội ngang nhau để trở thành một phần của sự kết hợp chiến thắng.
Chúng ta hãy điều tra câu hỏi này.
Tôi đã thu thập số liệu thống kê từ trang web của họ cho 1609 bản vẽ kéo dài từ năm 2009 đến năm 2023.
Sau đó, tôi đã chuyển đổi dữ liệu từ tệp CSV thành một đối tượng:
{ '09/09/2023': [13, 17, 24, 30, 35, 37], '07/09/2023': [7, 17, 19, 25, 35, 37], '05/09/2023': [2, 3, 5, 9, 36, 37], '02/09/2023': [4, 12, 22, 27, 30, 34], '29/08/2023': [6, 8, 15, 19, 26, 31], '26/08/2023': [6, 7, 14, 21, 25, 34], '22/08/2023': [2, 6, 10, 23, 24, 29], ... }
Khóa trong đối tượng tương ứng với ngày của bản vẽ và giá trị liên quan là một mảng các số xuất hiện dưới dạng kết hợp chiến thắng cho bản vẽ cụ thể đó.
Sau đó, tôi tạo một mảng chứa tất cả các số thu được từ các bản vẽ:
numbers = np.array(list(lotto.values())).flatten() [13, 17, 24, 30, 35, 37, 7, 17, 19, 25, 35, 37, 2, 3, 5, 9, 36, ...]
Sau đó, tôi tính số lần xuất hiện (tần suất) cho mỗi giá trị trong mảng:
count = np.bincount(numbers)[1:] [268, 256, 257, 242, 255, 273, 247, 277, 260, 267, 289, 294, 271, 239, 254, 255, 263, 243, 246, 271, 265, 254, 252, 243, 291, 271, 258, 264, 275, 258, 251, 244, 263, 256, 267, 251, 264]
Những kết quả này chỉ ra rằng số 1 được rút ra 268 lần, số 2 được rút ra 256 lần, v.v.
Có vẻ như sự phân bổ các con số trong kết quả xổ số là tương đối đồng đều. Để xác nhận thêm điều này, chúng tôi có thể tiến hành kiểm tra để xác nhận tính đồng đều của phân phối.
Để kiểm tra khả năng trang bị của N số riêng lẻ, bạn có thể làm theo phương pháp sau:
Thực hiện kiểm tra thống kê, chẳng hạn như kiểm tra chi bình phương, để xác định xem giá trị chi bình phương được tính toán có ý nghĩa thống kê hay không. Điều này sẽ giúp bạn đánh giá liệu sự phân bố của các con số có khác biệt đáng kể so với những gì được mong đợi trong khả năng trang bị hay không.
Nếu giá trị chi bình phương được tính toán không có ý nghĩa thống kê, điều đó cho thấy các con số được phân bổ đồng đều hợp lý, hỗ trợ cho giả thuyết về khả năng trang bị. Tuy nhiên, nếu giá trị X^2 lớn, nó sẽ cho thấy có sự khác biệt so với khả năng trang bị.
Hãy tạo một hàm để thực hiện kiểm tra chi bình phương về khả năng trang bị của các số:
def chi2(data, size, expect, p_value = 0.05): pl = size * 1/expect df = expect - 1 x2_crit_1 = stats.chi2.ppf(p_value, df) x2_crit_2 = stats.chi2.ppf(1 - p_value, df) x2 = 0 for i in range(expect): x2 += ((data[i] - pl) ** 2)/pl accepted = x2_crit_1 < x2 < x2_crit_2 if x2_crit_1 < x2_crit_2 else x2_crit_2 < x2 < x2_crit_1 return x2, accepted
Hàm này trả về bộ dữ liệu gồm thống kê chi bình phương và kết quả là khả năng trang bị được chấp nhận với xác suất 1 - 2 * p-value
, tức là các giá trị cực trị của phân bố đều rời rạc này có xác suất thấp.
N = 37 chi2(count, len(numbers), N) (25.183136523720748, True)
Chắc chắn, bạn có thể sử dụng chức năng tích hợp từ thư viện SciPy để thực hiện kiểm tra chi bình phương về khả năng trang bị:
from scipy import stats chi2_statistic, p_value = stats.chisquare(count) (25.18313652372074, 0.9115057832606053)
Hãy cùng khám phá sự kết hợp của những con số này, bắt đầu bằng các cặp:
from itertools import combinations pairs = list(combinations(range(1, N), 2))
Tiếp theo bước này, chúng tôi xây dựng ma trận 2D theo dõi sự xuất hiện của các cặp này:
pairs_count = np.zeros([N] * 2, dtype=int) for pair in pairs: for draw in lotto.values(): if pair[0] in draw and pair[1] in draw: pairs_count[pair[0]][pair[1]] += 1 pairs_count = pairs_count[1:, 1:]
Điều này tạo thành một ma trận tam giác, vì nó giải thích thực tế là các cặp (a, b) và (b, a) là tương đương nhau và chúng ta chỉ tính số lần xuất hiện của các cặp (a, b).
Chức năng của tôi mang lại:
counts = pairs_count.flatten() counts = counts[counts > 0] chi2(counts, sum(counts), len(counts)) (589.2721893491138, True)
và SciPy cung cấp:
chi2_statistic, p_value = stats.chisquare(counts) (589.2721893491124, 0.8698507423203673)
Làm thế nào về việc xem xét bộ ba:
comb3 = list(combinations(range(1, N), 3)) comb3_count = np.zeros([N] * 3, dtype=int) for comb in comb3: for draw in lotto.values(): contains = comb[0] in draw and comb[1] in draw and comb[2] in draw if contains: comb3_count[comb[0]][comb[1]][comb[2]] += 1 comb3_count = comb3_count[1:, 1:, 1:] counts = comb3_count.flatten() counts = counts[counts > 0] chi2(counts, sum(counts), len(counts)) (6457.575829383709, False)
Đã xảy ra sự cố, có thể do độ thưa thớt cao của ma trận. Giá trị chi bình phương giảm xuống dưới ngưỡng chi bình phương tới hạn thấp hơn:
6457.575829383709 < 6840.049842653838
Tuy nhiên khi sử dụng SciPy thì kết quả là:
chi2_statistic, p_value = stats.chisquare(counts) (6457.575829383886, 0.9999997038479482)
Bây giờ, hãy xác định số được rút ra thường xuyên nhất:
count.argmax() or list(count).index(max(count)) 11
Chúng ta đừng vội kết luận vội. Chúng ta có thể kiểm tra con số này đã phát triển như thế nào qua các năm:
year_result = dict() for year in range(2009, 2024): new_dict = {k:v for (k,v) in lotto.items() if str(year) in k} year_result[year] = np.bincount(np.array(list(new_dict.values())).flatten())[1:].argmax() { 2009: 16, 2010: 10, 2011: 11, 2012: 24, 2013: 32, 2014: 34, 2015: 21, 2016: 25, 2017: 5, 2018: 10, 2019: 24, 2020: 11, 2021: 12, 2022: 14, 2023: 11 }
Hoặc cách khác, chúng ta có thể phân tích những thay đổi tích lũy theo thời gian:
year_result = dict() arr = [] for year in range(2009, 2024): new_dict = {k:v for (k,v) in lotto.items() if str(year) in k} arr += list(np.array(list(new_dict.values())).flatten()) year_result['2009 - ' + str(year) if year > 2009 else str(year)] = np.bincount(arr)[1:].argmax() { '2009': 16, '2009 - 2010': 10, '2009 - 2011': 11, '2009 - 2012': 20, '2009 - 2013': 20, '2009 - 2014': 20, '2009 - 2015': 34, '2009 - 2016': 20, '2009 - 2017': 10, '2009 - 2018': 10, '2009 - 2019': 10, '2009 - 2020': 10, '2009 - 2021': 10, '2009 - 2022': 24, '2009 - 2023': 11 }
Cuối cùng, chúng ta cũng có thể điều tra xem liệu các bản vẽ giống hệt nhau có từng xuất hiện hay không:
lotto_counts = {} for k, v in lotto.items(): v_str = str(v) if v_str in lotto_counts: lotto_counts[v_str] += [k] else: lotto_counts[v_str] = [k] result = {k: v for k, v in lotto_counts.items() if len(lotto_counts[k]) > 1} { '[13, 14, 26, 32, 33, 36]': ['16/10/2010', '21/09/2010'] }
Thật thú vị khi lưu ý rằng những sự việc này xảy ra gần như liên tiếp.
Khi chúng tôi kết thúc hành trình của mình vào thế giới dữ liệu xổ số, đó là một chuyến đi đầy thử thách với các con số và xác suất. Chúng tôi đã phát hiện ra một số thông tin thú vị – từ cặp và bộ ba cho đến việc tìm ra những con số phổ biến nhất.
Xổ số là một trò chơi không thể đoán trước được, nhưng thật thú vị khi lén nhìn vào phía sau bức màn và khám phá những điều kỳ quặc của những trò chơi này. Cho dù bạn là người chơi hay chỉ là một người quan sát tò mò, thế giới của những con số luôn có một hoặc hai điều bất ngờ.