Eksik değerler için birden çok gösterim


13

Belirli kısıtlamalar altında veri kümemdeki eksik değerleri değiştirmek için gösterim kullanmak istiyorum.

Örneğin, isnat edilen değişkenin x1diğer iki değişkenimin toplamından daha büyük veya eşit olmasını isterim, diyelim x2ve x3. Ben de istiyorum x3biri tarafından izafi edilecek 0veya >= 14ve istediğim x2biri tarafından izafi edilecek 0veya >= 16.

Bu kısıtlamaları SPSS'de birden çok gösterim için tanımlamayı denedim, ancak SPSS'de sadece maksimum ve minimum değerleri tanımlayabilirim. SPSS'de başka kısıtlamalar tanımlamanın herhangi bir yolu var mı veya eksik değerlerin ithali için bu tür kısıtlamaları tanımlamama izin verecek herhangi bir R paketi biliyor musunuz?

Verilerim aşağıdaki gibidir:

   x1 =c(21, 50, 31, 15, 36, 82, 14, 14, 19, 18, 16, 36, 583, NA,NA,NA, 50, 52, 26, 24)
   x2 = c(0, NA, 18,0, 19, 0, NA, 0, 0, 0, 0, 0, 0,NA,NA, NA, 22, NA, 0, 0)
   x3 = c(0, 0, 0, 0, 0, 54, 0 ,0, 0, 0, 0, 0, 0, NA, NA, NA, NA, 0, 0, 0)
   dat=data.frame(x1=x1, x2=x2, x3=x3)
   > dat
       x1 x2 x3
   1   21  0  0
   2   50 NA  0
   3   31 18  0
   4   15  0  0
   5   36 19  0
   6   82  0 54
   7   14 NA  0
   8   14  0  0
   9   19  0  0
   10  18  0  0
   11  16  0  0
   12  36  0  0
   13 583  0  0
   14  NA NA NA
   15  NA NA NA
   16  NA NA NA
   17  50 22 NA
   18  52 NA  0
   19  26  0  0
   20  24  0  0

Değiştim 0 or 16 or >= 16için 0 or >= 16çünkü >=16değeri içerir 16. Umarım anlamını bozmaz. Aynı için0 or 14 or >= 14
Alexis

Yanıtlar:


16

Bir çözüm, micepaket için kendi özel imputation işlevlerinizi yazmaktır . Paket bunun için hazırlanmıştır ve kurulum şaşırtıcı derecede acısızdır.

Öncelikle verileri önerildiği gibi ayarlıyoruz:

dat=data.frame(x1=c(21, 50, 31, 15, 36, 82, 14, 14, 19, 18, 16, 36, 583, NA,NA,NA, 50, 52, 26, 24), 
               x2=c(0, NA, 18,0, 19, 0, NA, 0, 0, 0, 0, 0, 0,NA,NA, NA, 22, NA, 0, 0), 
               x3=c(0, 0, 0, 0, 0, 54, 0 ,0, 0, 0, 0, 0, 0, NA, NA, NA, NA, 0, 0, 0))

Sonra micepaketi yükler ve varsayılan olarak hangi yöntemleri seçtiğini görürüz:

library(mice)
# Do a non-imputation
imp_base <- mice(dat, m=0, maxit = 0)

# Find the methods that mice chooses
imp_base$method
# Returns: "pmm" "pmm" "pmm"

# Look at the imputation matrix
imp_base$predictorMatrix
# Returns:
#   x1 x2 x3
#x1  0  1  1
#x2  1  0  1
#x3  1  1  0

pmmAçılımı öngörü ortalama eşleştirme sürekli değişkenler imputing için muhtemelen en popüler töhmet algoritması -. Bir regresyon modeli kullanarak tahmin edilen değeri hesaplar ve tahmin edilen değere en yakın 5 elemanı seçer ( Öklid mesafesine göre ). Bu seçilen elemanlara donör havuzu denir ve nihai değer bu donör havuzundan rastgele seçilir.

Tahmin matrisinden, yöntemlerin kısıtlamalar için ilgi çekici değişkenleri aldığını görüyoruz. Satırın hedef değişken ve sütun öngörücüler olduğunu unutmayın. X1'in x3 sütununda 1 yoksa, bunu matriste eklememiz gerekir:imp_base$predictorMatrix["x1","x3"] <- 1

Şimdi eğlenceli kısma, çarpma yöntemlerini üretiyoruz. Burada, kriterleri karşılamayan tüm değerleri attığım oldukça kaba bir yöntem seçtim. Bu, uzun döngü süresine neden olabilir ve geçerli impütasyonları korumak ve sadece geri kalanları yeniden yapmak potansiyel olarak daha verimli olabilir, ancak biraz daha tweaking gerektirir.

# Generate our custom methods
mice.impute.pmm_x1 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    max_sum <- sum(max(x[,"x2"], na.rm=TRUE),
                   max(x[,"x3"], na.rm=TRUE))
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals < max_sum)){
        break
      }
    }
    return(vals)
  }

mice.impute.pmm_x2 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals == 0 | vals >= 14)){
        break
      }
    }
    return(vals)
  }

mice.impute.pmm_x3 <- 
  function (y, ry, x, donors = 5, type = 1, ridge = 1e-05, version = "", 
            ...) 
  {
    repeat{
      vals <- mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                              version = "", ...)
      if (all(vals == 0 | vals >= 16)){
        break
      }
    }
    return(vals)
  }

Yöntemleri tanımladıktan sonra, önceki yöntemleri basitçe değiştiriyoruz. Sadece tek bir değişkeni değiştirmek istiyorsanız, sadece kullanabilirsiniz, imp_base$method["x2"] <- "pmm_x2"ancak bu örnek için hepsini değiştireceğiz (adlandırma gerekli değildir):

imp_base$method <- c(x1 = "pmm_x1", x2 = "pmm_x2", x3 = "pmm_x3")

# The predictor matrix is not really necessary for this example
# but I use it just to illustrate in case you would like to 
# modify it
imp_ds <- 
  mice(dat, 
       method = imp_base$method, 
       predictorMatrix = imp_base$predictorMatrix)

Şimdi üçüncü gizli veri kümesine bir göz atalım:

> complete(imp_ds, action = 3)
    x1 x2 x3
1   21  0  0
2   50 19  0
3   31 18  0
4   15  0  0
5   36 19  0
6   82  0 54
7   14  0  0
8   14  0  0
9   19  0  0
10  18  0  0
11  16  0  0
12  36  0  0
13 583  0  0
14  50 22  0
15  52 19  0
16  14  0  0
17  50 22  0
18  52  0  0
19  26  0  0
20  24  0  0

Tamam, iş bu. Bu çözümü beğendim, çünkü ana işlevlerin üstüne geri dönebilir ve sadece anlamlı bulduğunuz kısıtlamaları ekleyebilirsiniz.

Güncelleme

Yorumlarda belirtilen titiz kısıtlamaları @ t0x1n zorlamak için, sarma işlevine aşağıdaki yetenekleri eklemek isteyebiliriz:

  1. Önceki, kısmen başarılı çalışmalardan alınan verilerin atılmaması için döngüler sırasında geçerli değerleri kaydedin
  2. Sonsuz döngülerden kaçınmak için bir kaçış mekanizması
  3. Uygun bir eşleşme bulmadan x kez denedikten sonra donör havuzunu şişirin (bu öncelikle pmm için geçerlidir)

Bu, biraz daha karmaşık bir sarma işleviyle sonuçlanır:

mice.impute.pmm_x1_adv <-   function (y, ry, 
                                      x, donors = 5, 
                                      type = 1, ridge = 1e-05, 
                                      version = "", ...) {
  # The mice:::remove.lindep may remove the parts required for
  # the test - in those cases we should escape the test
  if (!all(c("x2", "x3") %in% colnames(x))){
    warning("Could not enforce pmm_x1 due to missing column(s):",
            c("x2", "x3")[!c("x2", "x3") %in% colnames(x)])
    return(mice.impute.pmm(y, ry, x, donors = 5, type = 1, ridge = 1e-05,
                           version = "", ...))
  }

  # Select those missing
  max_vals <- rowSums(x[!ry, c("x2", "x3")])

  # We will keep saving the valid values in the valid_vals
  valid_vals <- rep(NA, length.out = sum(!ry))
  # We need a counter in order to avoid an eternal loop
  # and for inflating the donor pool if no match is found
  cntr <- 0
  repeat{
    # We should be prepared to increase the donor pool, otherwise
    # the criteria may become imposs
    donor_inflation <- floor(cntr/10)
    vals <- mice.impute.pmm(y, ry, x, 
                            donors = min(5 + donor_inflation, sum(ry)), 
                            type = 1, ridge = 1e-05,
                            version = "", ...)

    # Our criteria check
    correct <- vals < max_vals
    if (all(!is.na(valid_vals) |
              correct)){
      valid_vals[correct] <-
        vals[correct]
      break
    }else if (any(is.na(valid_vals) &
                    correct)){
      # Save the new valid values
      valid_vals[correct] <-
        vals[correct]
    }

    # An emergency exit to avoid endless loop
    cntr <- cntr + 1
    if (cntr > 200){
      warning("Could not completely enforce constraints for ",
              sum(is.na(valid_vals)),
              " out of ",
              length(valid_vals),
              " missing elements")
      if (all(is.na(valid_vals))){
        valid_vals <- vals
      }else{
        valid_vals[is.na(valid_vals)] <- 
          vals[is.na(valid_vals)]
      }
      break
    }
  }
  return(valid_vals)
}

Büyük olasılıkla, önerilen veri kümesinin tüm durumlar için kısıtlamaları kaybolmadan başarısız olması nedeniyle, bu kadar iyi çalışmadığını unutmayın . Davranmaya başlamadan önce döngü uzunluğunu 400-500'e çıkarmam gerekiyor. Bunun kasıtsız olduğunu varsayıyorum, dürüstlüğünüz gerçek verilerin nasıl üretildiğini taklit etmelidir.

Optimizasyon

Argüman ryeksik olmayan değerleri içerir ve uygun imputasyonlar bulduğumuz öğeleri kaldırarak döngüyü hızlandırabiliriz, ancak iç işlevlere aşina olduğum için bundan kaçındım.

Bence, tam doldurmaya zaman ayıran güçlü kısıtlamalarınız olduğunda en önemli şey , impütasyonlarınızı paralel hale getirmektir ( CrossValidated hakkındaki cevabıma bakın ). Çoğu bugün 4-8 çekirdekli bilgisayarlara sahiptir ve R varsayılan olarak bunlardan birini kullanır. Çekirdek sayısı iki katına çıkarılarak zaman (neredeyse) yarıya bölünebilir.

İmpütasyonda eksik parametreler

Sorununu İlişkin x2isnadın anda eksik olan - fareler aslında içine eksik değerleri besleyen asla x- data.frame. Farenin yöntemi başlangıcında rastgele değeri dolgu içerir. Empütasyonun zincir kısmı, bu ilk değerden gelen etkiyi sınırlar. mice-Function'a bakarsanız bunu imputing çağrısından önce ( mice:::sampler-function) bulabilirsiniz:

...
if (method[j] != "") {
  for (i in 1:m) {
    if (nmis[j] < nrow(data)) {
      if (is.null(data.init)) {
        imp[[j]][, i] <- mice.impute.sample(y, 
                                            ry, ...)
      }
      else {
        imp[[j]][, i] <- data.init[!ry, j]
      }
    }
    else imp[[j]][, i] <- rnorm(nrow(data))
  }
}
...

Bu data.initfonksiyona verilebilir miceve fareler.imput.sample , temel bir örnekleme prosedürüdür.

Ziyaret sırası

Ziyaret dizisi önemliyse, mice-fonksiyonunun impütasyonları yürütme sırasını belirleyebilirsiniz . Varsayılan, 1:ncol(data)ancak istediğiniz gibi olacak şekilde ayarlayabilirsiniz visitSequence.


+1 Bu harika şeyler, tam olarak aklımda olan şeydi (Frank'in cevabı hakkındaki yorumuma bakın) ve şu andan itibaren ödül için 1 numaralı aday. Birkaç şey hakkında sorun beni pmm_x1gerçi: (1) olası herhangi bir kombinasyonuyla azami toplamı alarak x2ve x3bütün veri kümesinden orijinal kısıtlama çok daha kiriş olduğunu. Doğru şey olduğunu test etmek olacaktır her satır için , x1 < x2 + x3. Elbette, ne kadar fazla satırınız varsa, böyle bir kısıtlamaya uyma şansınız o kadar küçük olur (tek bir kötü satır her şeyi mahveder) ve döngü potansiyel olarak daha uzun sürebilir.
t0x1n

(2) Her iki takdirde x1ve x2eksik, sen için bir değer atfetmek olabilir x1kez (hadi 50 say) hangi kısıtları tutulur, fakat x2(hadi o 55 olmak isnat söylüyorlar) onlar kırılır izafi olur. Dikey değil, "yatay" olarak dayatmanın bir yolu var mı? Biz tek bir satır suçlamak olabilir Bu şekilde x1, x2ve x3sadece yeniden atfetmek ve bu belirli satır kısıtlar altında düşene kadar. Bu yeterince hızlı olmalı ve bittiğinde bir sonraki satıra geçebiliriz. Tabii ki MI doğasında "dikey" ise şansımız kalmaz. Bu durumda, belki Aleksandr'un bahsettiği yaklaşım?
t0x1n

Harika bir çözüm, +1! Şu anda micepaketi kullandığım için özellikle kullanışlı olabilir . Paylaşım için teşekkürler.
Aleksandr Blekh

1
@ t0x1n Cevabınızı yorumlarınıza göre daha gelişmiş bir sarmalayıcı işleviyle güncelledim. Daha derine dalmak istiyorsanız , kardeşlerinin kaputun altında debug()nasıl mice.impute.pmmve nasıl çalıştığını görmek için ile oynamanızı tavsiye ederim .
Max Gordon

1
@ t0x1n: Sanırım - zımni değerlerinizi inceleyin. Gerçekçi görünmüyorlarsa, sadece modelin merkezinde olmayanları ima etmek için yaklaşımımı seçebilirsiniz. Benim durumumda, takip röntgenleri olmayanları çalışmanın kalbinde oldukları için hariç tutmayı seçtim ve impütasyonlar klinik olarak makul değerler sağlamıyor (bacak bir kırıktan sonra uzuyor). Bundan tamamen memnun değilim ama makul bir uzlaşma gibi görünüyor.
Max Gordon

8

Bulabildiğim en yakın şey Amelia'nın önceden bilgi içermesidir. Skeçte bölüm 4.7'ye , özellikle 4.7.2'ye bakın:

Gözlem düzeyi öncelikleri

Araştırmacılar genellikle önceki araştırmalara, akademik fikir birliğine veya kişisel deneyime dayanan eksik veri değerleri hakkında ek ön bilgiye sahiptir. Amelia, bu bilgiyi büyük ölçüde iyileştirilmiş impütasyonlar üretmek için dahil edebilir. Amelia algoritması, kullanıcıların birçoğu çok az doğrudan anlamı olan daha genel model parametreleri yerine bireysel eksik veri hücreleri hakkında bilgilendirici Bayesian öncelikleri dahil etmelerine izin verir.

Önceliklerin dahil edilmesi, impütasyonun modele dayalı impütasyonun ağırlıklı bir ortalaması olduğu temel Bayes analizini ve ağırlıkların verilerin göreceli gücünün ve önceki fonksiyonlarının işlevleri olduğu önceki ortalamanın ardından gelir: model çok iyi tahmin ettiğinde , ithalatın öncekinin ağırlığını azaltacağı gibi, bunun tersi de geçerlidir (Honaker ve King, 2010).

Bireysel gözlemlerle ilgili öncelikler analistin eksik veri hücresinin dağılımı hakkındaki inancını tanımlamalıdır. Bu ya bir ortalama ve standart bir sapma ya da bir kondens aralığı şeklinde olabilir. Örneğin, Tayland'da 1986 tarife oranlarının% 40 civarında olduğunu biliyoruz, ancak kesin değer konusunda bazı belirsizliklerimiz var. O halde, eksik veri hücresinin dağılımı hakkındaki önceki inancımız, önceki inancımızla ilgili belirsizlik miktarını yansıtan standart bir sapma ile 40'a odaklanır.

Öncelikleri girmek için dört veya beş sütunlu bir öncelikler matrisi oluşturmanız gerekir. Matrisin her satırı, bir gözlem veya bir değişken üzerinde bir önceliği temsil eder. Herhangi bir satırda, ilk sütundaki giriş gözlemin sırasıdır ve giriş ikinci sütunda gözlemin sütunu olur. Dört sütun önceki matrisinde, üçüncü ve dördüncü sütunlar, eksik değerin önceki dağılımının ortalama ve standart sapmasıdır.

Genelde böyle bir şey söyleyemeseniz de x1<x2+x3, veri kümenizin üzerinden geçebilir ve her ilgili durum için bir gözlem düzeyi ekleyebilirsiniz. Sabit sınırlar da uygulanabilir (x1, x2 ve x3'ü negatif olmayacak şekilde ayarlamak). Örneğin:

priors = matrix(NA, nrow=0, ncol=5);
for (i in seq(1, length(data))) 
{
    x1 = data$x1[i];
    x2 = data$x2[i];
    x3 = data$x3[i];

    if (is.na(x1) && !is.na(x2) && !is.na(x3))
    {
        priors = rbind(priors, c(i, 1, 0, x2+x3, 0.999999))
    }
}

amelia(data, m=1, bound = rbind(c(1, 0, Inf), c(2, 0, Inf), c(3, 0, Inf)), pr = priors);

5

Kısıtlamaların tahmin edici ortalamada çoklu çarpma ile uygulanması daha kolaydır. Bu, kısıtlamaları karşılayan eksik kısıtlayıcı değişkenlerle önemli sayıda gözlem olduğunu varsayar. Bunu R Hmiscpaket aregImputeişlevinde uygulamayı düşünüyorum . Bir ay içinde tekrar kontrol etmek isteyebilirsiniz. Bir donör gözleminin olabileceği hedeften maksimum mesafeyi belirtmek önemlidir, çünkü kısıtlamalar donörleri ideal kısıtlanmamış donörden daha fazla iter.


Ben de buna sahip olmak isterdim. Sadece en temel değişkenler arası kısıtlamalara ihtiyacım var x<y<z.
t0x1n

Eğer yolum kesilirse cehaletimi affedin, ama birden fazla impütasyon tekniğinin uygun bir dağılımdan değer çizmeyi içerdiği izlenimi altındaydım. Reddetme örneklemesi kullanmak basit bir mesele değil mi? örneğin, belirli bir kısıtlama (örneğin x1<x2) karşılanıncaya kadar çizim yapmaya devam etmek istiyor musunuz?
t0x1n

aregImputeÖngörülü ortalama eşleşmesi ile R işlevi ile yapabileceğim budur . Peki ya donör gözlemlerinin hiçbiri (tahminlerin yakın maçları), donör değişkenler kümesi üzerindeki kısıtlamaları karşılamak zorunda olsalar bile, hedef gözlemin getirdiği kısıtlamaları karşılamıyorsa ne olur?
Frank Harrell

Böyle bir durumda, tahmin edilen değeri doğrudan alın? Bu sadece böyle bir örnek için regresyona (PMM fazı olmadan) dayanıyor mu?
t0x1n

Regresyon tüketiminin, öznenin geri kalanıyla tutarsız olan örtülü değerlerle ortaya çıkması biraz daha olasıdır. Bu yüzden PMM'den kaçınmanın bir nedeni olduğunu düşünmüyorum.
Frank Harrell

4

Amelia(Amelia II) paketinin şu anda veri değerleri aralığı kısıtlamalarını belirtmek için en kapsamlı desteğe sahip olduğuna inanıyorum . Ancak sorun, Ameliaverilerin çok değişkenli normal olduğunu varsaymasıdır.

Sizin durumunuzda, çok değişkenli normallik varsayımı geçerli değilse, zincirleme denklemler aracılığıyla birden fazla itme (MI) miceuygulayan paketi kontrol etmek isteyebilirsiniz . Bu paketin çok değişkenli normallik varsayımı yoktur . Ayrıca, kısıtlamaları belirtmek için yeterli olabilecek bir işleve sahiptir , ancak ne derece olduğundan emin değilim. İşlev çağrılır . Bu konuda belgeleri şu adreste okuyabilirsiniz: http://cran.r-project.org/web/packages/mice/mice.pdf . Ek bir faydası, kullanıcı tanımlı impütasyon fonksiyonlarının belirlenmesine ve daha geniş algoritma seçimine izin verme esnekliğidir. İşte MI gerçekleştirmek için bir öğretici, kullanarak :squeeze()micemicehttp://www.ats.ucla.edu/stat/r/faq/R_pmm_mi.htm .

Anladığım kadarıyla, Dr. Harrell'in Hmiscaynı zincirleme denklemler ( tahmini ortalama eşleştirme ) yaklaşımını kullanan paketi , muhtemelen normal olmayan verileri ( normpmmyöntem hariç ) destekliyor . Belki de yukarıdaki cevabına göre kısıtlama şartname işlevselliğini zaten uygulamıştır. Kullanmadım aregImpute(), bu yüzden daha fazla şey söyleyemem (kullandım Ameliave mice, ama kesinlikle istatistik konusunda uzman değilim, sadece olabildiğince öğrenmeye çalışıyorum).

Son olarak, eksik değerlere sahip verilerin birden fazla ithalatı için yaklaşımların, yöntemlerin ve yazılımların biraz tarihli, ama yine de hoş bir şekilde genel bakışını bulabilirsiniz : http://www.ncbi.nlm.nih.gov/pmc/articles / PMC1839993 . MI hakkında daha yeni genel bakış belgeleri olduğundan eminim, ancak şu anda farkında olduğum şey bu. Umarım bu biraz yardımcı olur.


1
Bu güzel yorum, eksikleri gerçekte gözlemlenen değerlerle değiştiren tahmini ortalama eşleştirmenin, gözlenen tüm veriler bu kısıtlamaları karşıladığında zaten bazı tür çelişkiler içerebileceğini düşündürüyor. Bunu düşünen birini takdir ediyorum. Henüz özel bir kısıtlama uygulamamıştım aregImpute.
Frank Harrell

1
Haklısın. Sadece donör gözlemler ile tutarlı değerler sağlamak olduğunu fark onların diğer değişkenlerle değil, hedef değişkeni diğer değişkenlerle.
Frank Harrell

1
Amelia tarafından yapılan dağıtım varsayımlarının yanı sıra, cevabımda gösterdiğimden daha ayrıntılı kısıtlamalar belirleyebildiniz mi? Sorun squeeze, sınırlarının sabit olmasıdır, bu yüzden böyle bir şey belirtemezsiniz x1<x2. Ayrıca, çok geç olduğuna inandığım çarpık sonuç vektöründe çağrılmış gibi görünüyor. Bana öyle geliyor ki, sınırlama işlemi sırasında sınırlar göz önünde bulundurulmalıdır, bu yüzden gerçek sonrası bir düzenlemeden daha fazla anlamı vardır.
t0x1n

1
@ t0x1n: Ne yazık ki, kısıtlamaları belirtme şansım olmadı Amelia, çünkü micetestlerim verilerimin çok değişkenli olmadığını doğruladığında, ona geçtim . Ancak, son zamanlarda konuyla ilgili bu çok güzel sunum slaytları ile karşılaştım (MI yöntemleri ve yazılımı): statistik.lmu.de/~fkreuter/imputation_sose2011/downloads/… . Doğru anladıysam, kısıtlama sorununa olası bir çözümü açıklar (bkz. PDF sayfa 50 - slayt numarası 50 değil!). Bu yardımcı olur umarım.
Aleksandr Blekh

1
@ t0x1n: Aslında, çözüm 50 ve 51. sayfalarda açıklanmaktadır.
Aleksandr Blekh

0

Sorunuzu doğru bir şekilde anlarsam, eksik değişkenlerin hangi kısıtlamalara tabi olması gerektiğini zaten biliyorsunuzdur. SPSS'de çok muhalif değilim ama RI'de bunu yapmak için bir işlev yazabileceğinizi düşünüyorum (bu, deneyime bağlı olarak çok zor olmamalı). Bu tür kısıtlamalarla çalışan herhangi bir paket bilmiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.