Pertanyaan Menetapkan ID grup dengan ddply


Pertanyaan kinerja yang cukup mendasar dari seorang R newbie. Saya ingin menetapkan ID grup untuk setiap baris dalam bingkai data dengan kombinasi bidang yang unik. Inilah pendekatan saya saat ini:

> # An example data frame
> df <- data.frame(name=c("Anne", "Bob", "Chris", "Dan", "Erin"), 
                   st.num=c("101", "102", "105", "102", "150"), 
                   st.name=c("Main", "Elm", "Park", "Elm", "Main"))
> df
   name st.num st.name
1  Anne    101    Main
2   Bob    102     Elm
3 Chris    105    Park
4   Dan    102     Elm
5  Erin    150    Main
> 
> # A function to generate a random string
> getString <- function(size=10) return(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse=''))
>
> # Assign a random string for each unique street number + street name combination
> df <- ddply(df, 
              c("st.num", "st.name"), 
              function(x) transform(x, household=getString()))
> df
   name st.num st.name  household
1  Anne    101    Main 1EZWm4BQel
2   Bob    102     Elm xNaeuo50NS
3   Dan    102     Elm xNaeuo50NS
4 Chris    105    Park Ju1NZfWlva
5  Erin    150    Main G2gKAMZ1cU

Meskipun ini berfungsi baik untuk frame data dengan relatif sedikit baris atau sejumlah kecil grup, saya mengalami masalah kinerja dengan set data yang lebih besar (> 100.000 baris) yang memiliki banyak grup unik.

Ada saran untuk meningkatkan kecepatan tugas ini? Mungkin dengan idata.frame eksperimental plyr ()? Atau saya akan tentang ini semua salah?

Terima kasih sebelumnya atas bantuan Anda.


7
2017-07-17 20:26


asal


Jawaban:


Coba gunakan id function (juga dalam plyr):

df$id <- id(df[c("st.num", "st.name")], drop = TRUE)

Memperbarui:

Itu id fungsi dianggap tidak berlaku lagi sejak versi dplyr 0.5.0. Fungsi itu group_indices menyediakan fungsi yang sama.


14
2017-07-18 13:05



Apakah perlu bahwa ID menjadi string acak 10 karakter? Jika tidak, mengapa tidak hanya menyisipkan bersama kolom dari frame data. Jika ID harus memiliki panjang karakter yang sama, ubah faktor menjadi numerik, lalu tempelkan bersama-sama:

df$ID <- paste(as.numeric(df$st.num), as.numeric(df$st.name), sep = "")

Kemudian, jika Anda benar-benar perlu memiliki 10 ID karakter, saya akan menghasilkan hanya n jumlah ID, dan mengganti nama tingkat ID dengan mereka

df$ID <- as.factor(df$ID)
n <- nlevels(df$ID)

getID <- function(n, size=10){
  out <- {}
  for(i in 1:n){
    out <- c(paste(sample(c(0:9, LETTERS, letters), size, replace=TRUE), collapse=''))
  }
  return(out)
}

newLevels <- getID(n = n)

levels(df$ID) <- newLevels

Juga, sebagai samping, Anda tidak perlu menggunakannya function(x) dengan ddply dengan cara itu transform(). Kode ini akan berfungsi sama saja:

ddply(df, c("st.num", "st.name"), transform, household=getString())

2
2017-07-17 20:57