2016-03-20 24 views
9

İki değişkenin ("ManufactererId" ve "ProductId") kombinasyonunun benzersiz anahtarları/tanımlayıcıları oluşturduğu verilerim var. veri aşağıdaki gibidir:Bir data.frame dosyasına eklenecek çift indeksli/anahtarlı satırlar nasıl önlenir?

Ben yanlışlıkla ManufactererId bir çift başka bir satır ekleyemezsiniz sağlamak istiyoruz
my.data <- data.frame(ManufactererId = c(1, 1, 2, 2), 
         ProductId = c(1, 2, 1, 7), 
         Price = c(12.99, 149.00, 0.99, 3.99)) 
my.data 
# ManufactererId ProductId Price 
# 1    1   1 12.99 
# 2    1   2 149.00 
# 3    2   1 0.99 
# 4    2   7 3.99 

- (bir veritabanı tablosu üzerinde benzersiz kısıtlama gibi) Tabloda zaten mevcut olanı eşit productID .

my.data <- rbind(my.data, data.frame(ManufactererId = 2, ProductId = 7, Price = 120.00)) 

... bir hata ile başarısız olmalıdır: benim veri çerçevesine ManufactererId = 2 ve ProductID = 7 içeren bir satır eklemeye çalışırsanız, bir

. Bu nasıl başarılabilir?

Veya farklı bir veri türü kullanmalı mıyım?

cevap

7

1) zoo Bunun uygun olup olmadığı, ne tür işlemler yapmak istediğinize bağlı olarak değişir ancak hayvanat bahçesi nesneleri benzersiz dizinlere sahiptir. İki Id sütununu bir araya getirerek bir metin dizini oluşturabiliriz. Yukarıda gösterilen olarak veya bir matris veri sadece fiyat daha fazla olması gibi bir hayvanat bahçesi nesnesinin veri bölümü için bir vektör olabilir

library(zoo) 
z <- with(my.data, zoo(Price, paste(ManufactererId, ProductId))) 

z <- c(z, zoo(90, "1 1")) # Error, not appended 
z <- c(z, zoo(90, "1 3")) # OK 

not edin.

2) SQLite Bu, herhangi bir veritabanında herhangi biriyle yapılabilir, ancak burada SQLite kullanacağız. Önce bir SQLite veritabanında benzersiz bir dizin içeren bir tablo oluşturduk ve sonra satırları ekliyoruz.

library(RSQLite) 

con <- dbConnect(SQLite()) 
dbWriteTable(con, "my", my.data, row.names = FALSE) 
dbGetQuery(con, "create unique index ix on my(ManufactererId, ProductId)") 

dbGetQuery(con, sprintf("insert into my values(%d, %d, %d)", 1, 1, 99)) # error 
dbGetQuery(con, sprintf("insert into my values(%d, %d, %d)", 1, 13, 90)) # OK 
+0

İkinci yaklaşım eklendi. –

6

Böyle bir şey yapabilirsiniz: keys benzersiz anahtar

append_save <- function(DF, to_be_appended, keys=c("ManufactererId", "ProductId")){ 
    if(ncol(DF) != ncol(to_be_appended) || !all(names(DF) %in% names(to_be_appended))){ 
    stop("must have the same columns") 
    } 
    if(nrow(merge(DF, to_be_appended, by=keys))==0){ 
    rbind(DF, to_be_appended) 
    } else { 
    stop("Trying to append douplicated indices") 
    } 
} 

Testi nerede olduğunu:

to_be_appended = data.frame(ManufactererId=2,ProductId=17,Price=3.99) 
append_save(my.data, to_be_appended) # works 
to_be_appended_err = data.frame(ManufactererId=2,ProductId=7,Price=3.99) 
append_save(my.data, to_be_appended_err) # error 

yalnızca anahtar sütunları temel veri eklemesi durumunda yapabildin aşağıdaki gibi data.table kullanın:

1

Temel R'de bunu yapmanın bir yolu, bir environment sözlük veya karma map benzeri nesne olarak kullanmaktır. my.dict < - yeni.

make_key <- function(ManufactererId, ProductId) 
    paste(ManufactererId, ProductId) 

set_value <- function(key, value, dict){ 
     ## checking here assures desired behavior 
     if(any(key %in% names(dict))) 
      stop("This key has been used") 
     assign(key, value, envir=dict) 
} 

sonra env()

Birincisi, yazma bazı yardımcı fonksiyonları, değerleri ayarlamak için

keys <- make_key(my.data[[1]], my.data[[2]]) 

gibi tuşları oluşturabilir, biraz daha dikkatli olmak gerekir

# don't just do this as the first element is used by assign 
# set_value(keys, my.data[[3]], dict=my.dict) 

mapply(set_value, keys, my.data[[3]], MoreArgs = list(dict=my.dict)) 
ls.str(my.dict) # better than str for environments 
# 1 1 : num 13 
# 1 2 : num 149 
# 2 1 : num 0.99 
# 2 7 : num 3.99 

set_value("1 1", 4, my.dict) 
# Error in set_value("1 1", 4, my.dict) : This key has been used 
0

Yinelenen veriler hariç yeni verileri kopyalamanın basit yolu:

library(data.table) 
my.data = data.table(ManufactererId = c(1, 1, 2, 2), 
        ProductId = c(1, 2, 1, 7), 
        Price = c(12.99, 149.00, 0.99, 3.99), 
        key = c("ManufactererId","ProductId")) 
x = my.data # my data will be called 'x' 
y = data.table(ManufactererId = 2, ProductId = 7, Price = 120.00) 
rbind(x, y[!x, on=key(x)]) 
# ManufactererId ProductId Price 
#1:    1   1 12.99 
#2:    1   2 149.00 
#3:    2   1 0.99 
#4:    2   7 3.99 

bir anahtar ayarlamak ama sadece doğrudan on argüman karakter vektör sunmaktır gerekmese de . Veri yapısına ilişkin iş beklentilerimizi yansıtan anahtar kullanmanın faydalı olduğunu düşünüyorum.


siz şu kullanabilirsiniz Böyle bir durumda bir hata yükseltmek isterseniz: y satır

unique.rbind = function(x, y, by=key(x)) { 
    if (nrow(x[y, nomatch=0L, on=by])) stop("duplicates in 'y'") 
    rbind(x, y) 
} 
unique.rbind(x, y) 
# Error in unique.rbind(x, y) : duplicates in 'y' 

Hiçbiri hatası durumunda eklenen alır.

İlgili konular