[Math] 班佛定律 Benford's law

數學知識:班佛定律

簡介:班佛定律的原理

自然界首數的機率並不是平均分配的,像是河川的長度、戶頭的金錢,甚至是請人們隨機選出的四位數字
b 進位制中,以數 n 起頭的數出現的機率為
P(n)=logb(n+1)logb(n)logb(b)logb(1)=logb(n+1)logb(n)=logb(n+1n)=logb(1+1n)
一組平均增長的數據開始時,增長得較慢
由最初的數字 a 增長到另一個數字 a+1 起首的數的時間
必然比 a+1 起首的數增長到 a+2,需要更多時間,所以出現率就更高了
從數數目來說,順序從1開始數,1,2,3,...,9,從這點終結的話,所有數起首的機會似乎相同
但 9 之後的兩位數 10 至 19,以 1 起首的數又大大拋離了其他數了
而下一堆 9 起首的數出現之前,必然會經過一堆以 2,3,4,...,8 起首的數
若果這樣數法有個終結點,以 1 起首的數的出現率一般都比 9 大
或者換個角度來看
增長的速度需為幾何成長,才有此現象
因為無論是 2x10xex,取 log 後,皆會變為線性
而由於每段分配類似梯型,因基數極大,導致上底與下底差異小,所以會由高決定機率
若是 [1,10),分別機率為 log10(2)log10(1)log10(3)log10(2)...log10(10)log10(9)
而若是 [10,100),分別機率為 log10(20)log10(10)log10(30)log10(20)...log10(100)log10(90)
實際上也是一樣的,因為 log 相減等於相除

十位數首數分配機率

人們隨性所寫出的數,銀行帳簿的存款數據,河流的區域
面積,都市的人口數據,公司的收支數據等,都會有底下的分佈比例

n123456789
P(n)30.1%17.6%12.5%9.7%7.9%6.7%5.8%5.1%4.6%

10x 首數分配

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3.  
  4. def getFirst(x):
  5. if x < 10:
  6. return int(x)
  7. else:
  8. return getFirst(x//10)
  9. f = np.vectorize(getFirst)
  10.  
  11. data = np.random.rand(10000)
  12. data = np.floor(10**data)
  13. x = f(data)
  14. plt.hist(x, bins=range(1, 11), density=True)
  15. plt.show()

台股股價首數分佈

  1. import requests
  2. import pandas as pd
  3. import time
  4. from pyquery import PyQuery
  5. import matplotlib.pyplot as plt
  6.  
  7.  
  8. # 得到首位數
  9. def getFirst(x):
  10. if x < 10:
  11. return int(x)
  12. else:
  13. return getFirst(x//10)
  14.  
  15. # 得到股票代碼
  16. def getSymbolList():
  17. url = "http://isin.twse.com.tw/isin/C_public.jsp?strMode=2"
  18. dom = PyQuery(url)
  19. data = []
  20. for i, row in enumerate(dom('table.h4 tr').items()):
  21. if i < 2:
  22. continue
  23. item = []
  24. for j, col in enumerate(row.find('td')):
  25. if col.text:
  26. if j == 0: # 分開代碼與名字
  27. item.extend(col.text.strip().split('\u3000'))
  28. else:
  29. item.append(col.text.strip().replace('\u3000', ''))
  30. if item:
  31. data.append(item)
  32. else: # 只取上市部分
  33. return data
  34. return data
  35. # Alpha Vantage API
  36. def alphaVantage(function, symbol, interval='1min'):
  37. url = "https://www.alphavantage.co/query"
  38. headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; rv:57.0) Gecko/20100101 Firefox/57.0",
  39. "Connection": "keep-alive",
  40. }
  41. api_key = "xxxx" #your key
  42.  
  43. params = {"function": function,
  44. "symbol": symbol,
  45. "interval": interval,
  46. "apikey": api_key}
  47. c = 0
  48. while True:
  49. page = requests.get(url, params=params)#, headers=headers)
  50. data = page.json()
  51. if len(data) >= 2:
  52. return data
  53.  
  54. c += 1
  55. if c > 5:
  56. break
  57. time.sleep(1)
  58. print(data, page.url)
  59. return data
  60.  
  61. # 得到股票價格
  62. def getStockPrice(symbol):
  63. history= alphaVantage('TIME_SERIES_INTRADAY', symbol)
  64. last = history.get('Meta Data')
  65. if last is None:
  66. return 0.0
  67. last = last['3. Last Refreshed']
  68. price = history['Time Series (1min)'][last]['4. close']
  69. if price:
  70. print(symbol, float(price))
  71. return float(price)
  72. if __name__ == '__main__':
  73. data = getSymbolList()
  74. df = pd.DataFrame(data)
  75. df = df.ix[:,[0,1]].dropna()
  76. df = df.rename(index=int, columns={0:'symbol', 1:'name'})
  77. df.ix[:, 'symbol'] = df['symbol'] + '.TW'
  78. df.ix[:, 'price'] = 0
  79. # 取得價格
  80. df = df.reset_index(drop=True)
  81. for i, symbol in enumerate(df['symbol']):
  82. if df.ix[i, 'price'] == 0:
  83. df.ix[i, 'price'] = getStockPrice(symbol)
  84. df.ix[:, 'first'] = df['price'].apply(getFirst)
  85. plt.hist(df['first'], bins=range(1, 11), density=True)
  86. plt.show()

參考

不要相信你的直覺
Wiki 班佛定律
52 班佛法則...不會丟擲骰子的上帝?
A Statistical Derivation of the Signi cant-Digit Law

留言