Polish Python Coders Group Forum

Wszystko o języku Python => Python od podstaw => Wątek zaczęty przez: leo9997 16:45 14/11/17



Tytuł: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: leo9997 16:45 14/11/17
Zadanie 3 do zrobienia(załącznik)
Kod
import math
def Pearson(x,y):
if len(x)==len(y):
x,y=[float(i) for i in x],[float(i) for i in y]
n,l,m1,m2=len(x),0,0,0
x0,y0=(sum(x)/n),(sum(y)/n)
 
for i in range(n):
l+=(x[i]-x0)*(y[i]-y0)
m1+=((x[i]-x0)**2)
m2+=((y[i]-y0)**2)
return l/(math.sqrt(m1)*math.sqrt(m2))
else:
raise ValueError('Listy muszą być jednakowej długości')
 
x=list(input('Podaj pierwszą listę ').split())
y=list(input('Podaj drugą listę ').split())
print(Pearson(x,y))

I znów pytanie czy da się to uprościć :( ? Proszę o pomoc, z góry dzięki :)


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: Guaz 18:16 14/11/17
Na przykład:
Kod
def Pearson(x,y):
if len(x)==len(y):
n = len(x)
x0, y0=(sum(x)/n), (sum(y)/n)
 
funct = lambda L, arg2: sum([(arg1-arg2)**2 for arg1 in L])**0.5
return sum([(xi-x0)*(yi-y0) for xi, yi in zip(x,y)])/(funct(x, x0)*funct(y, y0))
else:
raise ValueError('Listy muszą być jednakowej długości')
 
x=[float(i) for i in input('Podaj pierwszą listę ').split()]
y=[float(i) for i in input('Podaj drugą listę ').split()]
print(Pearson(x,y))
Albo mniej skomplikowany sposób z użyciem zip'a:
Kod
def Pearson(x,y):
if len(x)==len(y):
l, m1, m2 = 0,0,0; n = len(x)
x0, y0=(sum(x)/n), (sum(y)/n)
 
for xi, yi in zip(x, y):
l+=(xi-x0)*(yi-y0)
m1+=((xi-x0)**2)
m2+=((yi-y0)**2)
return l/(math.sqrt(m1)*math.sqrt(m2))
else:
raise ValueError('Listy muszą być jednakowej długości')
 
x=[float(i) for i in input('Podaj pierwszą listę ').split()]
y=[float(i) for i in input('Podaj drugą listę ').split()]
print(Pearson(x,y))

Jakby się postarać to wystarczy jedna linijka z rekurencją. Ale minus jest taki że po kilku dniach nawet jako autor zastanawiasz się co do cholery ty tam właśnie napisałeś ;P.


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: Guaz 18:25 14/11/17
W sumie, jako ciekawostka, bez rekurencji, ale można skompresować te lambdę w zmiennej funct, tylko pytanie po co ;d
Kod
def Pearson(x,y):
funct = lambda L, arg2: sum([(arg1-arg2)**2 for arg1 in L])**0.5
return sum([(xi-(sum(x)/len(x)))*(yi-(sum(y)/len(y))) for xi, yi in zip(x,y)])/(funct(x, (sum(x)/len(x)))*funct(y, (sum(y)/len(y)))) if len(x)==len(y) else ValueError('Listy muszą być jednakowej długości')
 
x=[float(i) for i in input('Podaj pierwszą listę ').split()]
y=[float(i) for i in input('Podaj drugą listę ').split()]
print(Pearson(x,y))/code]
 
I tak jest już nieczytelne.


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: leo9997 18:31 14/11/17
dobra nie miałem tego na wykładzie, jakaś magia :D. a moglibyście zerknąć na zad 4 ? Chodzi mi o podpunkt a), chciałem zrobić rekurencyjnie, a wyskakuje RecursionError
Kod
def Podzielnosc(n):
tab,suma=[],0
for i in reversed(x):
tab+=[int(i)]
for i in range(0,len(tab)):
suma+=tab[i]*(3**i)
if suma==7:
return True
else:
Podzielnosc(str(suma))
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))
nie wiem o co chodzi :D


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: Guaz 20:08 14/11/17
dobra nie miałem tego na wykładzie, jakaś magia :D.
zip'a warto się nauczyć, podstawowych generatorów również, bardzo ułatwiają robotę. Ale POD (pyramid of doom) to tylko jak jesteś fanboy'em pythona xP. W innych językach z reguły takich cudów nie zrobisz - dlatego nauka takich rozwiązań jest mało uniwersalna.

Co do zadania, najprościej z rekurencją:
Kod
def division_by(num, divi):
   if num==divi: return true;
   else if num < divi: return false;
   else: division_by(num-divi, divi);

W ten sposób możesz sprawdzić podzielność przez dowolną liczbę bez wykonywania dzielenia :).

@EDIT: Oczywiście są też specjalne zasady podzielności które masz w zadaniach, ale przyznam szczerze że nie rozumiem tych indeksów górnych/dolnych, więc nie jestem w stanie pomóc w sposób optymalizacyjny :s


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: leo9997 21:27 14/11/17
chodzi o to że dla przykładu mając liczbe 315 to jest to (5*10^0)+(1*10^1)+(3*10^2) czyli jest to suma a(i)*10^i gdzie a=[3,1,5]  i jest z range(0,len(a)).

Teraz dla a [3,1,5] liczby z tego drugiego wzoru  czyli a(i)*3^i czyli to jest (5*3^0)+(1*3^1)+(3*3^2)=35. I teraz bierzemy to 35 i znowu mielimy przez ten wzór i jak wyjdzie nam 7 na końcu to liczba 315 jest podzielna przez 7, a jak coś innego to nie jest :) Rozumiesz ? Nie wiem jak to zapisać rekurencyjnie


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: leo9997 21:40 14/11/17
i chyba to mam
Kod
def Podzielnosc(n):
if int(n)==7 or int(n)==0:
return True
else:
suma,tab=0,[int(i) for i in reversed(n)]
if len(tab)==1:
return False
else:
for i in range(0,len(tab)):
suma+=tab[i]*(3**i)
return Podzielnosc(str(suma))
 
def Podzielnosc1(n):
if int(n)==11 or int(n)==0:
return True
else:
suma,tab=0,[int(i) for i in n]
if len(tab)==1:
return False
else:
for i in range(0,len(tab)):
suma+=tab[i]*((-1)**i)
return Podzielnosc1(str(suma))
 
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))
print(Podzielnosc1(x))
teraz jak to zrobić prościej :D


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: Guaz 22:09 14/11/17
Domyślnie indeksowanie masz od zera:
Kod
for i in range(0,len(tab)) == for i in range(len(tab))

Badanie równości zajmuje najwięcej czasu o ile mnie pamięć nie myli.
Kod:
if len(n)==1:
else:
Więc lepiej to zamienić na coś innego:
Kod
if len(n)>1: #tu wykonujesz poprzedni else
else: #tu wykonujesz poprzednie else, w twoim programie nie jest możliwe by argument miał
        #długość zero, czyli był pustym stringiem w wyniku rekurencji, tylko wejście startowemoż

Kod
def Podzielnosc(n):
if int(n)==7 or int(n)==0:
return True
else:
if len(n)==1: return False; #Metoda len również działa dla łańcuchów znaków (metody string)
else:
suma,tab=None,[int(i) for i in reversed(n)] #Nie ma sensu tego generować jeśli n ma jeden znak długości.
suma = str( sum( [ tab[i]*(3**i) for i in range(len(tab)) ] ) ) #A tu generator jest wskazany.
return Podzielnosc(suma)
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))

Bardziej zrozumiała wersja /\

Mniej zrozumiała:
Kod
def Podzielnosc(n):
   if int(n)==7 or int(n)==0: return True;
   return Podzielnosc(str( sum( [ [int(j) for j in reversed(n)][i]*(3**i) for i in range(len(n)) ] ) )) if len(n)>1 else False
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))
 

@Edit:
Zoptymalizowana:
Mniej zrozumiała:
Kod
def Podzielnosc(n):
   if int(n)==7 or int(n)==0: return True;
   return Podzielnosc(str( sum( [ j*(3**i) for i, j in zip(range(len(n)),[int(g) for g in reversed(n)]) ] ) )) if len(n)>1 else False
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))
 


Tytuł: Odp: Współczynnik korelacji Pearsona
Wiadomość wysłana przez: leo9997 22:45 14/11/17
Zostawiam tak
Kod
def Podzielnosc(n):
if int(n)==7 or int(n)==0:
return True
else:
if len(n)==1:
return False
else:
suma,tab=None,[int(i) for i in reversed(n)]
suma=str(sum([tab[i]*(3**i) for i in range(len(tab))]))
return Podzielnosc(suma)
 
def Podzielnosc1(n):
if int(n)==11 or int(n)==0:
return True
else:
if len(n)==1:
return false
else:
suma,tab=None,[int(i) for i in n]
suma=(sum([tab[i]*((-1)**i) for i in range(len(tab))]))
if suma>=0:
return Podzielnosc1(str(suma))
else:
return False
 
x=str(input('Podaj liczbę naturalną '))
print(Podzielnosc(x))
print(Podzielnosc1(x))

Tyle kumam :D