Monday, June 25, 2012

add_subplot(222)?

Matplotlib (ve Matlab) ana grafik ekranini bolerek ufak grafikleri bu bolumlere koyma yetenegine sahip. Bu orneklere bakarken, belki de 332, 222 gibi sayilar kullanildigini gormussunuzdur. Mesela

fig = plt.figure()
ax1 = fig.add_subplot(321,title="baslik")
ax1.plot(data1)

gibi. Burada 321'in anlami sudur: Ana ekran 3 satir ve 2 kolon olmak uzere, yani 3x2 olarak bolunecek, ve ustteki grafik 1'inci bolume konacak.

1., 2. tabii ki sol ustten baslanip saga dogru gidince artan sayilar, yani hucrelerin indisi.

O zaman 321'in 32 kismi diger tum alt grafikler icin tekrarlanacak. Yeni grafikler 322, 323, 324, vs gibi gidecekler.

Tablo Alanlari ve Postgresql

Eger buyuk bir taban ile calisiyorsaniz, bir sure sonra Postgresql'in olagan (default) tanimladigi yerde (cogunlukla ana dizin '/' altinda) bir sure sonra yerinizin bitmeye basladigini farkedebilirsiniz. Cozum, veri tabanini yaratirken hangi diskin kullanilacagini Postgresql'a soylemek.

Once bir tablo alani (tablespace) yaratirsiniz,



# create tablespace tablo_alan_ismi location '/filanca/dizin' ;

# create database taban_ismi tablespace=tablo_alan_ismi;

Artik taban dosyalari /filanca/dizin altina yazilacak.

PyMC

Cok seviyeli hiyerarsik model kullanimi icin BUGS, JAGS, PyMC'den bahsettik. PyMC kurulumu icin

sudo apt-get install gfortran

Kaynak kodlar

http://pypi.python.org/pypi/pymc#downloads

python setup.py  build
sudo python setup.py install

Ornek kod

https://github.com/burakbayramli/gelman-arm-bda-python/blob/master/arm/

dizini altinda

radon_varying_intercept.py
16.3-PYMC.py
srrs.csv

dosyalari lazim. Ana kod 16.3-PYMC.py.


Wednesday, June 20, 2012

Google Analytics'den Script ile Veri Almak

Bilindigi gibi bir sitenin kullanim verilerini GA'ye kaydettirmek mumkun. GA siteniz hakkinda bir suru degerli bilgiyi kayit edecek, ve bir admin araci uzerinden sunacak. Eger bu bilgileri, en azindan gunluk bazinda ozetlenmis bir kismini, kendi sisteminize ham veri olarak almak istiyorsaniz, GA'nin Python ile baglanilacak bir arayuzu var.

http://code.google.com/p/gdata-python-client/

Kurduktan sonra gdata-2.0.17/samples/analytics altina bakin, burada data_feed_demo.py var. Bu kod komut satirindan elle kullanici, sifre falan istiyor, tam bitmis halde degil. Bu kodun __init__ kismini soyle degistirin:

  def __init__(self):
     SOURCE_APP_NAME = 'Google-dataFeedDemoPython-v2'
    my_client = gdata.analytics.client.AnalyticsClient(source=SOURCE_APP_NAME)

    # your pass needs to be in $HOME/pass file
    password = open("%s/pass" % os.environ['HOME']).read()   
    try:
      my_client.client_login("[KULLANICI]",password,SOURCE_APP_NAME,
                             service='analytics')
     
    except gdata.client.BadAuthentication:
      exit('Invalid user credentials given. Please your password in $HOME/pass file')
    except gdata.client.Error:
      exit('Login Error')

    table_id = "ga:[TABLO ID]"


[TABLO ID] nedir? GA admin aracina girince URL'e bakin, p23234 gibi bir kisim var, p'den sonra gordugunuz tum sayilari alip [TABLO ID] icin kullanabilirsiniz.

Ustteki degisim sonrasi sifreniz $HOME/pass adli bir dosyadan geliyor olacak, boylece koda gommeniz gerekmez.

Ornegin geri kalaninda ga:visits verisinin alindigi gorulur, bu sadece ziyaret verisi, daha fazlasi da var. Tam liste icin suraya bakiniz.

Bir degisik ornek,

import numpy as np
import gdata.analytics.client
import gdata.sample_util
import os

SOURCE_APP_NAME = 'Google-dataFeedDemoPython-v2'
my_client = gdata.analytics.client.AnalyticsClient(source=SOURCE_APP_NAME)

# your pass needs to be in $HOME/pass file
password = open("%s/pass" % os.environ['HOME']).read()   
try:
  my_client.client_login("[KULLANICI]",password,SOURCE_APP_NAME,
                         service='analytics')
 
except gdata.client.BadAuthentication:
  exit('Invalid user credentials given. Please your password in $HOME/pass file')
except gdata.client.Error:
  exit('Login Error')

table_id = "[TABLO ID]"

# DataFeedQuery simplifies constructing API queries and uri encodes params.
data_query = gdata.analytics.client.DataFeedQuery({
    'ids': table_id,
    'start-date': '2012-04-01',
    'end-date': '2012-06-24',
    'dimensions': 'ga:date',
    'metrics': 'ga:visits,ga:newVisits,ga:percentNewVisits,ga:visitors,ga:bounces,ga:timeOnSite',
    'sort': 'ga:date',
    'max-results': '10000'})

feed = my_client.GetDataFeed(data_query)

data = []

for entry in feed.entry:
  line = []

  for dim in entry.dimension:
    line.append( int(dim.value.replace("-",""))  )
  for met in entry.metric:
    line.append(float(met.value))
  data.append(line)
 
data = np.array(data)

np.savetxt("foo.csv", data, delimiter=",", fmt='%10.2f')


Bu kodla gunluk bazda bir suru olcum noktasini aliyoruz, kolonlar olarak bir matris icine yerlestiriyoruz, ve csv dosyasi olarak diske yaziyoruz.

Harf Kaydirarak Sifreleme

def helper(message, ift):
        message = message.lower()
        sec = ""
        for c in message:
                if c in "abcdefghijklmnopqrstuvwxyz":
                        num = ord(c)
                        num += ift
                        if num > ord("z"):     # wrap if necessary
                                num -= 26
                        elif num < ord("a"):
                                num += 26
                        sec = sec + chr(num)
                else:
                        sec = sec + c
        return sec

def e(message):
        return helper(message, 3)

def d(message):
        return helper(message, -3)
Anahtar kelimeler: code, decode, encrypt, decrypt

Tuesday, June 12, 2012

Birikmeli (Cumulatif) Toplamlar ve SQL

Mesela dellstore2 tabaninda tum siparisler uzerindeki "aktif musterileri" bulmak istiyoruz. Aktif musterinin tanimi orders tablosunda olmaktan ibaret, o zaman tekil (unique) olarak

select count(distinct(customerid)) from orders

dersek, tum zamanlar icin gerekli rakami bulabiliriz. Fakat ya bize birikimsel (cumulative) olarak, ay bazinda yavas yavas buyuyen bir rakam bulmamiz istenseydi? O zaman Postgresql'in OVER (ORDER BY ...) numarasini kullanmamiz lazim. Dikkat, burada PARTITION komutu yok.

Fakat aklimiza ilk gelen basit kodlamayi yaparsak

select 
date_trunc('month',orderdate),
sum(count(distinct(customerid))) over (order by date_trunc('month',orderdate))
from orders group by date_trunc('month',orderdate) 

dogru sonucu almadigimizi goreceksiniz. Sebep farkli aylardaki customerid kayitlarinin toplami sisirmesidir. Tekil musteri sayisini aradigimiz icin bu bize dogru sonucu vermiyor. O zaman her customerid icin tek bir tarih kullanmamiz gerekir, tercihen musterinin ilk yaptigi siparisin ay kismi kullanilabilir. Ornek

SELECT 
OrderDate,SUM(COUNT(DISTINCT customerid)) OVER (ORDER BY OrderDate)
FROM   
(  
 SELECT CustomerID,
        DATE_TRUNC('MONTH', MIN(OrderDate)) AS OrderDate
        FROM    orders
        GROUP BY CustomerID
) AS orders
GROUP BY OrderDate

Goruldugu gibi min(..) ile customerid icin mumkun olabilecek en erken tarih alinmis. Bu kod toplami duzeltecektir.

Link

Saturday, June 9, 2012

Python Ile Mail - Metin Eklentileri (Text Attachement)

Python script icinden otomatik email gondermek ve mesaja txt, csv dosyasi eklemek icin alttaki mail.py adli script kullanilabilir. Script SMTP servisi olarak localhost, yani yerel makinada bir SMTP servisi oldugunu farz ediyor. Bu servisin yeri degistirilebilir, mesela bir GMail hesabi ve SMTP servisi de kullanilabilir.

import smtplib, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
    assert type(send_to)==list
    assert type(files)==list

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

    for f in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(f,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)

    smtp = smtplib.SMTP(server)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()


Kullanimi

import datetime
import mail
import sys

start = datetime.datetime.now()
date = datetime.datetime.today().strftime('%Y-%m-%d')

mail.send_mail('nereden@filan.com',
               ['nereye@falan.com'],
               '%s tarihinde gonderilen mesaj' % date,
               'Mesaj basligi .. ',
               ['dosya1.csv','dosya2,csv'])



Sunday, June 3, 2012

Python ile API Bazli Postgresql Erisimi

Gerekli paket pyscopg. Python DB arayuzunu gerceklestiren (implement) bir paket, yani MySql tabanlara baglanti icin kod yazanlar icin cagrilar tanidik gelecektir. En basit ornek test.py adli bir dosya olsun,

import psycopg2

conn = psycopg2.connect("dbname=[taban] user=postgres password=postgres")
cur = conn.cursor()
cur.execute("SELECT * from tablo limit 1")
print cur.fetchone()

Isletmek icin

sudo -u postgres python test.py

Numpy Temelli 2 Kolon Icin Basit Gruplama (Group By)

SQL'deki group by komutunun Numpy karsiligi. 2 kolon bazinda calisiyor, tum islemler hafizada.

import numpy as np
import itertools

def group2(arr):
    rows,cols = arr.shape
    res = []
    c = 0
    for unique_0,unique_1 in itertools.product(np.unique(arr[:,0]), np.unique(arr[:,1])):
        tmp = arr[arr[:,0] == unique_0]
        tmp = tmp[tmp[:,1] == unique_1]
        res.append([unique_0, unique_1, len(tmp)])
    return np.array(res)

if __name__ == "__main__":
    a = np.array([[1,2,5,4,5,5],
                  [4,5,3,4,4,3]])
    print group2(a.T)
    print group2(a.T).shape

Zamansal Veriyi Puruzsuzlestirmek (Smoothing)

Bazen ham veriyi oldugu gibi grafikleyince cok inisli, cikisli olabiliyor, ki cogu zaman gormek istedigimiz bir trend oluyor. O zaman grafigi daha kabaca, puruzsuz bir egri olarak gostermek gerekebilir. Puruzleri gidermek icin bircok teknik var, "surekli hareket eden ortalama penceresi (running average)" bu yollardan biri. Fikir basit, belli buyuklukte (mesela 3,4 ya da 7 ogelik) bir pencere hayal edilir, ve bu pencere teker teker tum verileri alacak sekilde hareket ettirilir, ve pencerenin icine dusen tum degerlerin ortalamasi alinir, ve esas verideki veri yerine bu ortalama kullanilir. Ornek altta. Grafikte mavi renkli esas veri (rasgele uretildi), kirmizi olan daha kavisli olan ortalama.

from pylab import *
import numpy as np
import random

WINDOW = 7; weightings = repeat(1.0, WINDOW) / WINDOW

data = [random.random() for x in range(100)]

av = convolve(data, weightings)[WINDOW-1:-(WINDOW-1)]

plot(data)

hold(True)

plot(av,'r')

show()


Kategorik Veriyi Tamsayi (Indis) Bazina Cevirmek

Veri analizinde bazen kategorik veriler yerine pur sayi kullanmak gerekebilir. Ozellikle regresyon islemleri tam sayilari alarak islem yapabilirler, bu yuzden, mesela 'YAZ', 'BAHAR', gibi mevsim verisini kelime olarak iceren veriyi tam sayi bazli, 1,2,3.. turune cevirmek gerekebilir. Hizli bir yontem, Numpy unique cagrisina return_inverse secenegi vermek. Bu cagri bilindigi gibi verilerin tekil bir ozetini geri getirir,

a = np.array( ['a', 'b', 'c', 'a', 'b', 'c'])

print np.unique(a)

geriye

['a' 'b' 'c']

dondurur. Ek secenek ile indis degerlerini de alabilirsiniz,

b, c = np.unique(a, return_inverse=True)

print c

su sonucu verir

[0 1 2 0 1 2]

CSV Kolon Isimleri ve Python

CSV dosyalarini (virgulle ayrilmis, kolon, satir bazli text dosyalari) okumanin kolay yollarindan biri

data = np.genfromtxt("test.csv",names=True,delimiter=",",dtype=None)

Bu komut CSV'nin ilk satirinin kolon "isimlerini" tasidigini farz eder. Okuma sonrasi elde edilen data objesi bir tuple listesidir. Yani listelerin listesi degil, tuple objelerinin listesi. Bir Python tuple icinde farkli tipte objeler yanyana durabilir, bu yuzden o secilmis herhalde.

Kolon ismi kullanarak o kolonun verisine erismek istiyorsak,

print data['kolon']

kullanilir. Tum kolon isimlerini almak icin

data.dtype.names

erisimi yapilabilir. 

Friday, June 1, 2012

Enlemler, Boylamlar ve PostgreSql PostGis

Lokasyon bazli veri isleyebilmek icin Postgresql'in Postgis eklentisi gerekli. Bu eklenti ile enlem (latitude), boylam (longitude) kordinat verileri tabanda depolanabilir, dunya uzerinde "geometrik alanlar" tanimlanarak mesela belli kordinatlarin o alanlarin icine dusup dusmedigi sorgulanabilir. Ya da bir veya daha fazzla geometrik sekilin kesisim noktasinin nasil, ne buyuklukte, nerede bir baska bicim olacagini hesaplatirabilirsiniz. Suradaki

http://trac.osgeo.org/postgis/wiki/UsersWikiPostGIS20Ubuntu1110src

tarifler takip edilebilir. GDAL ve GEOS'u biz kaynaklardan kurduk.

sudo apt-get install gdal-bin

http://trac.osgeo.org/geos/

Sonra

sudo -u postgres psql

ile girip

\c [taban]

ile istediginiz tabana baglanin. Unutmayalim, eklentiler (extensions) taban bazli yaratilir. Sonra

CREATE EXTENSION postgis;

ile gerekli tipi yaratiriz.

\dT geography

ve

\dT geometry

ile tiplerin yaratildigini kontrol edin. Bu konu hakkinda ornek kodlar bu yaziya eklenecek.