積分

積分とは、微分の逆を行うことです。
ある式を微分したものを積分すると、元の式に戻ります。(但し微分で省略された部分は除く)
例えば、
5*t**2 + 2*t + 8
を微分すると、
10*t + 2
になりますが、これを積分すると、
5*t**2 + 2*t
になり、元の式(微分で省略された部分は除く)に戻っていることが分かります。

# 微分
from sympy import Symbol, Derivative
t = Symbol('t')
St = 5*t**2 + 2*t + 8
d = Derivative(St, t)
dd = d.doit()
print('微分', dd)

# 積分
from sympy import Integral
i = Integral(dd, t)
print('積分', i.doit())

結果は、以下の様になります。
微分 10*t + 2
積分 5*t**2 + 2*t



偏微分


偏微分は、変数が複数ある式の内、1つの変数だけ変化して他の変数は固定の式の微分のことです。
例えば、2*x**2 + y**2を、xについて偏微分すると、
>>> from sympy import Symbol, Limit, Derivative
>>> x = Symbol('x')
>>> y = Symbol('y')
>>> fxy = 2*x**2 + y**2
>>> fxy
2*x**2 + y**2
>>> d = Derivative(fxy, x)
>>> dd = d.doit()
>>> dd
4*x

となります。




微分

Derivativeを使えば微分できます。

from sympy import Symbol, Derivative
t = Symbol('t')
St = 5*t**2 + 2*t + 8
d = Derivative(St, t)
dd = d.doit()
print(dd.subs({t: 2}))

5*t**2 + 2*t + 8を微分すると、
2*5*t + 2となるので、
tに2を代入すると、結果は以下になります。
22


極限

sympyのLimitを使えば極限が求められます。
Sは無限大などの色々な記号の集まりです。

from sympy import Limit, Symbol, S

x = Symbol('x')
l = Limit(1/x, x, S.Infinity)
print(l.doit())
結果は0になります。

上の例の、S.Infinity(無限大)を0にすれば、結果はoo(無限大)となります。


数式をグラフ表示

sympyを使えば、数式をグラフに表示できます。
以下の例は、x**2 + 5x + 4を、xが-10から10の範囲にして出力します。

# グラフを描画
from sympy.plotting import plot
x = Symbol('x')
expr = x**2 + 5*x + 4
plot(expr, (x, -10, 10), title='X', xlabel='x', ylabel='x**2+5x+4')

結果は以下の様になります。





複数の式もグラフ表示できます。
# グラフを描画(2つ)
from sympy.plotting import plot
x = Symbol('x')
expr1 = x**2 + 5*x + 4
expr2 = 6*x + 1
p = plot(expr1, expr2, 1, title='X', xlabel='x', show=False)
p[0].line_color = 'r'
p[1].line_color = 'b'
p.show()

line_colorを設定しているのは、sympyのplotは線の表示色が全て同じになってしまうので、別々の色を設定するために行っています。
結果は以下の様になります。





連立方程式の解

sympyを使えば、連立方程式の解も求められます。

# 連立方程式の解
x = Symbol('x')
y = Symbol('y')
expr1 = 2*x + 2*y - 6
expr2 = 3*x + 2*y - 12
d = solve((expr1, expr2), dict=True)
print(d)

答えは、
[{x: 6, y: -3}]
と表示されます。

解が合ってるか確認するには、subsで上の答えをそれぞれの式に代入してみて0が返却されるか確認します。
# 解が合ってるか検証(0が出力されれば合ってることが分かる)
print(expr1.subs({x:6, y:-3}))
print(expr2.subs({x:6, y:-3}))

解が合ってるので(当然ですが)、下の様に表示されます。
0
0


文字列を数式化する

プログラムで数式を生成するのではなく、文字列から数式を生成するには、sympyのsympifyを使います。

from sympy import sympify
from sympy.core.sympify import SympifyError

expr = (input('Enter a mathematical expression: '))

try:
expr = sympify(expr)
except SympifyError:
print('Invalid input')


代数に値を与える

subsを使えば、代数に値を与えて計算することができます。
以下の例では、
x2 + 2xy + y2
の式のxとyにそれぞれx=1、y=2を代入して計算します。


>>> import sympy
>>> x = sympy.Symbol('x')
>>> y = sympy.Symbol('y')
>>> expr = x*x+2*x*y+y*y
>>> expr
 2            2
y  + 2⋅x⋅y + x 
>>> res = expr.subs({x:1, y:2})
>>> res
9

12 + 2*1*2 + 22
となるので、答えは9になります。


式の展開

因数分解した後の式を展開するには、Sympyを使います。
例えば、
y=(x+2)(x+3)
の式を展開すると、
y=x**2 + 5*x + 6
になりますが、このように展開式を求めるには、以下の様にします。

>>> import sympy
>>> y = (x + 2) * (x + 3)
>>> y
(x + 2)*(x + 3)
>>> sympy.expand(y)
x**2 + 5*x + 6


因数分解

因数分解をするにはライブラリのSympyを使います。factorで因数分解をします。

>>> import sympy
>>> x = sympy.Symbol('x')
>>> y = sympy.Symbol('y')
>>> y = x**2 + 5*x + 6
>>> y
x**2 + 5*x + 6
>>> sympy.factor(y)
(x + 2)*(x + 3)


相関係数

相関係数とは、2つの集合がどの程度関係があるかを示す指標となるものです。
例えば、ある月の気温の集合と、同一月のアイスクリームの売り上げの集合があるとして、気温とアイスクリームの売り上げという集合が、どの程度相関しているかを示すのに使われたりします。

相関係数-1〜1までの範囲で取得でき、-1、または1に近いほど2つの集合が相関していることを示しています。
ただし、相関係数が-1、または1に近いからといって必ず相関しているわけではなく、一応の目安程度のものとなっています。
例えば上の例で言うと、アイスクリームの売り上げが高かった月と同じ月に殺人事件が多かったとしたら、相関係数は多分1に近くなるかもしれませんが、殺人事件とアイスクリームの売り上げが関係しているとはどう考えても思えません。

相関係数は、以下の式で求められます。

2つの集合の要素数:N(2つの集合の要素数は同じである必要があります。)
集合X:x
集合Y:y

              NΣxy - ΣxΣy
------------------------------------
  √(NΣx2-(Σx)2)(NΣy2-(Σy)2)


def correlation(x, y):
''' 2つの集合の分散係数を求める
x:集合x
y:集合y
集合xと集合yの要素数は同一であること '''
mulsum = 0
sum_squared_x = 0
sum_squared_y = 0
for xi, yi in zip(x, y):
# x, yの積和
mulsum = mulsum + xi * yi
# xの二乗和
sum_squared_x = sum_squared_x + xi ** 2
# yの二乗和
sum_squared_y = sum_squared_y + yi ** 2
# xの和
sum_x = sum(x)
# yの和
sum_y = sum(y)
# xの和の二乗
squared_sum_x = sum_x**2
# yの和の二乗
squared_sum_y = sum_y**2
N = len(x)
# 分子
numerator = N * mulsum - sum_x * sum_y
# 分母
denominator = ((N * sum_squared_x - squared_sum_x)
* (N * sum_squared_y - squared_sum_y)) ** 0.5
return numerator / denominator

x = [1, 2, 3, 4, 5, 6]
y = [10, 11, 12, 13, 14, 15]
c = correlation(x, y)
print('correlation of x, y is ', c)



中央値

中央値配列の中央の位置にある要素の値です。
要素数が奇数の場合はぴったり真ん中の位置が求まりますが、偶数の場合は真ん中の要素が2つになるので、真ん中の2つの要素の平均が中央値となります。

def median(arr):
N = len(arr)
sorted_arr = sorted(arr)
if N % 2 == 0:
# 偶数
val1 = sorted_arr[int(N / 2) - 1]
val2 = sorted_arr[int(N / 2)]
return (val1 + val2) / 2
else:
# 奇数
return sorted_arr[int((N + 1) / 2) - 1]

arr = [3, 6, 1, 10, 8, 7, 9]
med = median(arr)
print('median of array{0} is {1}'.format(arr, med))
median of array[3, 6, 1, 10, 8, 7, 9] is 7





フィボナッチ数列

フィボナッチ数列とは、各要素が前の2つの要素の和となった数列です。
要素数が多くなるにつれて、隣り合う2つの要素の比率が黄金比(1.61803・・・)に近づいていきます。

>>> def fib(n):
...   if n == 1:
...     return [1]
...   elif n == 2:
...     return [1, 1]
...   a = 1
...   b = 1
...   arr = [a, b]
...   for i in range(n):
...     c = a + b
...     arr.append(c)
...     a = b
...     b = c
...   return arr
... 
>>> fib(10)

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

>>> 144/89
1.6179775280898876
最後の2要素の比率が黄金比に近いです。
フィボナッチ数列を10個しか出していないので少数以下3桁目以降が違いますが、もっと多くの要素数を出すと黄金比(1.61803・・・)に近づいていきます。


投射運動

投射運動とは、例えばボールを投げた時にボールが描く軌跡のことです。
ここでは簡略化のため、水平方向の力にかかる空気抵抗などは省略しています。

ボールが地面に落ちるまでの時間(秒)は、
2 * (初速 * sin(ボールを投げる角度)) / 9.8
で求められます。


from matplotlib import pyplot as plt, axis
import math
def draw_graph(x, y):
plt.axis(ymax=x[len(x)-1])
plt.plot(x, y)

def frange(start, end, interval):
numbers = []
while start < end:
numbers.append(start)
start = start + interval
return numbers

def draw_trajectory(u, theta):
theta = math.radians(theta)
g = 9.8
# 地面に落ちるまでの時間
t_flight = 2 * u * math.sin(theta) / g
intervals = frange(0, t_flight, 0.001)
x = []
y = []
for t in intervals:
x.append(u * math.cos(theta) * t)
y.append(u * math.sin(theta) * t - 0.5 * g * t * t)
draw_graph(x, y)

# 初速25m/sでボールを角度45度で投げた時の軌跡
draw_trajectory(25, 45)
# 初速40m/sでボールを角度45度で投げた時の軌跡
draw_trajectory(40, 45)
# 初速60m/sでボールを角度45度で投げた時の軌跡
draw_trajectory(60, 45)
plt.show()



実行結果は、以下のようになります。



2物質の引力

2つの質量を持つ物質の引力は、下記のようにします。

>>> G = 6.674 * (10 ** -11)
>>> # Gは重力定数
>>> # 距離100m離れた物質、0.5kgと10kgの物質がお互いに引き付け合う引力
>>> force = G * (0.5 * 10.0) / (100.0 ** 2)
>>> force
3.337e-14

>>> 


2次方程式の解

2次方程式の解は、以下のようにします。

>>> def roots(a, b, c):
...   D = (b * b - 4 * a * c) ** 0.5
...   x_1 = (-b + D) / (2 * a)
...   x_2 = (-b - D) / (2 * a)
...   return {'x1':x_1, 'x2':x_2}

>>> # x**2 + 5x + 4 = 0の解

>>> roots(1, 5, 4)

{'x1': -1.0, 'x2': -4.0}



>>> # x**2 + 5x + 6 = 0の解
>>> roots(1, 5, 6)
{'x1': -2.0, 'x2': -3.0}

sympyを使えばもっと簡単に求められます。
以下の例では、解答を辞書形式で出力したり、ax2+bx+cの様な式でも解答が得られる例も示してあります。
from sympy import Symbol, solve
x = Symbol('x')
expr = x**2 + 5*x + 4
s = solve(expr)
print(s)

# dict=Trueで解答を辞書形式で返却してくれる
d = solve(expr, dict=True)
print(d)

# ax**2+bx+cみたいな式も対応可能
x = Symbol('x')
a = Symbol('a')
b = Symbol('b')
c = Symbol('c')
expr = a*x**2 + b*x + c
# xの解を得る
d = solve(expr, x, dict=True)
print(d)

摂氏⇄華氏変換

華氏を摂氏に変換するには、以下のようにします。
>>> def fahrenheit2celsius(fahrenheit):
...   return (fahrenheit - 32) * (5 / 9)
>>> fahrenheit2celsius(100)
37.77777777777778

摂氏を華氏に変換するには、以下のようにします。
>>> def celsius2fahrenheit(celsius):
...   return celsius * (9 / 5) + 32
>>> celsius2fahrenheit(37.777777777778)
100.0000000000004



キロメートル⇄マイル変換

1マイルは約1.609キロメートルなので、以下のようにします。
>>> def mile2km(mile):
...   return mile * 1.609
>>> mile2km(650)
1045.85

また、キロメートルをマイルに変換するには、以下のようにします。
>>> def km2mile(km):
...   return km / 1.609
>>> km2mile(1045.85)

650.0


メートル⇄インチ変換

メートルをインチに変換するには、以下のようにします。
>>> def m2inch(m):
...   return (m * 100) / 2.54

>>> m2inch(0.647699999999999)
25.499999999999964

また、インチをメートルにするには、以下のようにします。
>>> def inch2m(inch):
...   return (inch * 2.54) /100

>>> inch2m(25.5)
0.6476999999999999




因数の判定

aがbで割り切れる場合、bはaの因数です。

以下の例は、2と3がそれぞれ123の因数かを出力します。
>>> def is_factor(a, b):
...   if a % b == 0:
...     return True
...   else:
...     return False
... 
>>> is_factor(123, 2)
False
>>> is_factor(123, 3)

True
123は2で割り切れないので2は123の因数ではありません。
123は3で割り切れるので3は123の因数です。

以下の例は、1〜123までの因数を出力します。
>>> # 1〜123の因数のみ出力
>>> [n for n in range(1, 123) if is_factor(123, n)]

[1, 3, 41]



リストの2乗

リスト内の要素をそれぞれ2乗するには、以下のようにします。

>>> list = [1, 2, 3, 4, 5]
>>> result = []
>>> for n in list:
...   result.append(n**2)
... 
>>> print(result)

[1, 4, 9, 16, 25]

リスト内包表記(list comprehensions)を使えばもっと短く書けます。
>>> list = [1, 2, 3, 4, 5]
>>> result = [n ** 2 for n in list]
>>> print(result)
[1, 4, 9, 16, 25]



組み合わせ

組み合わせ5C2は、以下のようにして求めます。
>>> import itertools
>>> list(itertools.combinations(data, 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

組み合わせの数だけ分かれば良い場合は、
>>> len(list(itertools.combinations(data, 2)))
10

または、実際の組み合わせを生成しなくて良い場合は、
>>> import math
>>> math.factorial(len(data)) / (math.factorial(len(data) - 2) * math.factorial(2))
10.0

で求められます。

順列

順列は、itertoolsを使います。

例えば、5個中1個を選ぶ順列5P1は、
>>> # 5個中1個選ぶ順列
>>> import itertools

>>> data = (1, 2, 3, 4, 5)

>>> list(itertools.permutations(data))

[(1, 2, 3, 4, 5), (1, 2, 3, 5, 4), (1, 2, 4, 3, 5), (1, 2, 4, 5, 3), (1, 2, 5, 3, 4), (1, 2, 5, 4, 3), (1, 3, 2, 4, 5), (1, 3, 2, 5, 4), (1, 3, 4, 2, 5), (1, 3, 4, 5, 2), (1, 3, 5, 2, 4), (1, 3, 5, 4, 2), (1, 4, 2, 3, 5), (1, 4, 2, 5, 3), (1, 4, 3, 2, 5), (1, 4, 3, 5, 2), (1, 4, 5, 2, 3), (1, 4, 5, 3, 2), (1, 5, 2, 3, 4), (1, 5, 2, 4, 3), (1, 5, 3, 2, 4), (1, 5, 3, 4, 2), (1, 5, 4, 2, 3), (1, 5, 4, 3, 2), (2, 1, 3, 4, 5), (2, 1, 3, 5, 4), (2, 1, 4, 3, 5), (2, 1, 4, 5, 3), (2, 1, 5, 3, 4), (2, 1, 5, 4, 3), (2, 3, 1, 4, 5), (2, 3, 1, 5, 4), (2, 3, 4, 1, 5), (2, 3, 4, 5, 1), (2, 3, 5, 1, 4), (2, 3, 5, 4, 1), (2, 4, 1, 3, 5), (2, 4, 1, 5, 3), (2, 4, 3, 1, 5), (2, 4, 3, 5, 1), (2, 4, 5, 1, 3), (2, 4, 5, 3, 1), (2, 5, 1, 3, 4), (2, 5, 1, 4, 3), (2, 5, 3, 1, 4), (2, 5, 3, 4, 1), (2, 5, 4, 1, 3), (2, 5, 4, 3, 1), (3, 1, 2, 4, 5), (3, 1, 2, 5, 4), (3, 1, 4, 2, 5), (3, 1, 4, 5, 2), (3, 1, 5, 2, 4), (3, 1, 5, 4, 2), (3, 2, 1, 4, 5), (3, 2, 1, 5, 4), (3, 2, 4, 1, 5), (3, 2, 4, 5, 1), (3, 2, 5, 1, 4), (3, 2, 5, 4, 1), (3, 4, 1, 2, 5), (3, 4, 1, 5, 2), (3, 4, 2, 1, 5), (3, 4, 2, 5, 1), (3, 4, 5, 1, 2), (3, 4, 5, 2, 1), (3, 5, 1, 2, 4), (3, 5, 1, 4, 2), (3, 5, 2, 1, 4), (3, 5, 2, 4, 1), (3, 5, 4, 1, 2), (3, 5, 4, 2, 1), (4, 1, 2, 3, 5), (4, 1, 2, 5, 3), (4, 1, 3, 2, 5), (4, 1, 3, 5, 2), (4, 1, 5, 2, 3), (4, 1, 5, 3, 2), (4, 2, 1, 3, 5), (4, 2, 1, 5, 3), (4, 2, 3, 1, 5), (4, 2, 3, 5, 1), (4, 2, 5, 1, 3), (4, 2, 5, 3, 1), (4, 3, 1, 2, 5), (4, 3, 1, 5, 2), (4, 3, 2, 1, 5), (4, 3, 2, 5, 1), (4, 3, 5, 1, 2), (4, 3, 5, 2, 1), (4, 5, 1, 2, 3), (4, 5, 1, 3, 2), (4, 5, 2, 1, 3), (4, 5, 2, 3, 1), (4, 5, 3, 1, 2), (4, 5, 3, 2, 1), (5, 1, 2, 3, 4), (5, 1, 2, 4, 3), (5, 1, 3, 2, 4), (5, 1, 3, 4, 2), (5, 1, 4, 2, 3), (5, 1, 4, 3, 2), (5, 2, 1, 3, 4), (5, 2, 1, 4, 3), (5, 2, 3, 1, 4), (5, 2, 3, 4, 1), (5, 2, 4, 1, 3), (5, 2, 4, 3, 1), (5, 3, 1, 2, 4), (5, 3, 1, 4, 2), (5, 3, 2, 1, 4), (5, 3, 2, 4, 1), (5, 3, 4, 1, 2), (5, 3, 4, 2, 1), (5, 4, 1, 2, 3), (5, 4, 1, 3, 2), (5, 4, 2, 1, 3), (5, 4, 2, 3, 1), (5, 4, 3, 1, 2), (5, 4, 3, 2, 1)]

上のようにすると全ての並び順が出ますが、実際に並べたものじゃなくて並べた場合の数だけ知りたい時は以下のようにします。
len(list(itertools.permutations(data)))
120

または、mathを使えば実際の順列は生成されずに数だけ分かります。
>>> import math
>>> math.factorial(len(data))
120

5P2は以下のようにします。
>>> list(itertools.permutations(data, 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 4), (3, 5), (4, 1), (4, 2), (4, 3), (4, 5), (5, 1), (5, 2), (5, 3), (5, 4)]

同じく、数だけ知りたい時は、
>>> len(list(itertools.permutations(data, 2)))
20

実際の順列を生成したくない場合は、mathを使って、
>>> math.factorial(len(data)) / math.factorial(len(data) - 2)
20.0

とすれば求められます。





階乗

階乗は、math.factorialで求められます。

例えば、5!(=5 x 4 x 3 x 2 x 1)は以下のようにします。
>>> import math
>>> math.factorial(5)

120

math.factorialを使わないで行う場合は以下のようにします。
>>> fac = 1
>>> for i in range(1, 5 + 1):
...   fac = fac * i
... 
>>> print(fac)

120


複素数の大きさ

複素数の大きさは、実部の2乗+虚部の2乗を二乗根すれば求まります。

>>> C=(2+3j)
>>> (C.real**2+C.imag**2)**0.5
3.605551275463989

>>> C=complex(2, 3)
>>> (C.real**2 + C.imag**2)**0.5

3.605551275463989

また、abs関数でも同じことができます。
>>> C=(2+3j)
>>> abs(C)
3.605551275463989


共役複素数

複素数の、実部が同じで虚部の符号が異なるものを共役複素数といいます。

>>> (2+3j).conjugate()
(2-3j)
>>> complex(2, 3).conjugate()

(2-3j)

2+3iの共役複素数は、2-3iです。



複素数

複素数はj、または、complexで表します。
なぜjなのかというと、iは一般的に電流を表す記号として使われているからだそうです。

2+3i
>>> 2+3j
(2+3j)
>>> (2+3j)**2

(-5+12j)
(2+3i)の2乗をすると、
4 + 12i + (-9)となるので、
答えは-5 + 12iとなり、上の結果となります。

上と同じことは、以下の書き方でもできます。
>>> complex(2, 3)
(2+3j)
>>> complex(2, 3)**2
(-5+12j)

ちなみに、複素数の型は、
>>> type(2+3j)
<class 'complex'>

>>> type(complex(2, 3))
<class 'complex'>
となり、complex(複素数)となります。

複素数の計算には剰余(%)と床除算(//)は使えません。
実部を取得するには、realを使います。
>>> (2+3j).real
2.0
>>> complex(2, 3).real
2.0

また、虚部を取得するには、imagを使います。
>>> (2+3j).imag
3.0
>>> complex(2, 3).imag
3.0




分数

pythonでは分数を扱うライブラリが標準で用意されています。

3/4を分数で表す時は、Fraction(3, 4)とします。

以下、分数の例です。
>>> from fractions import Fraction
>>> f = Fraction(3, 4)
>>> f
Fraction(3, 4)
>>> f+1
Fraction(7, 4)
>>> f+2

Fraction(11, 4)

4分の3に1を足すと、4分の7になり、2を足すと4分の11になってることが分かります。



型を得る

pythonでは、typeで型を取得できます。

>>> type(1)
<class 'int'>
>>> type(1.0)
<class 'float'>
>>> type('1')

<class 'str'>


除算の結果を整数にする

除算の結果は通常は少数で返却されますが、以下のようにすると整数で返却されます。(少数以下切り捨て)

通常の除算
>>> 5/3
1.6666666666666667

# 答えが整数でも少数で返却される
>>> 4/2
2.0

除算の結果を整数で得る
>>> 5//3

1

>>> 4//2
2

ただし、-3を2で割るなど、除算結果がマイナスになる場合、除算の結果を超えない値が返却されます。
>>> -3/2
-1.5
普通の除算では-3割る2の答えは-1.5ですが、整数で返却するように//で除算すると、
>>> -3//2
-2
になります。
これは、-1.5より小さい整数を返却する為です。
//の除算は、ここら辺が少し紛らわしいかもしれません。





リストからのランダム選択

リストからランダムに選択するには、numpyrandom.choiceを使用します。

>>> import numpy as np
>>> data = np.array([1,2,3,4,5,6,7])
>>> np.random.choice(data)
6
>>> np.random.choice(data)
4
>>> np.random.choice(data)
1


標準偏差

標準偏差は、分散の累乗根を求めることで得られます。

>>> import numpy as np
>>> data = np.array([1,2,3,4,5,6,7])
>>> # 分散を求める
>>> dispersion = ((data - data.mean()) ** 2).sum() / len(data)
>>> np.sqrt(dispersion)
2.0

dispersionが分散。標準偏差は2.0になります。


分散

分散は、データのばらつき具合を表します。


>>> import numpy as np
>>> data = np.array([1,2,3,4,5,6,7])
>>> ((data - data.mean()) ** 2).sum() / len(data)

4.0

偏差の二乗和を求め、データ数で除算します。



平均

numpyの平均値取得は、averagemeanを使います。
averageは、データの各要素に重みをつけられます。
meanは重みをつけられません。

meanで平均を出す
import numpy as np
data = np.array([1,2,3,4,5,6,7])
np.mean(data)
# 4.0が出力されます。

averageで平均を出す
import numpy as np


data = np.array([1,2,3,4,5,6,7])
w = np.array([1, 1.5, 10.3, 4, 2, 1, 3])
np.average(data, weights=w)

# 3.855263157894737が出力されます。