2016-02-04 14 views
7

Często próbuję utworzyć kategoryczną zmienną ze zmiennej liczbowej + zestaw zakresów podany przez użytkownika.R: tworzenie zmiennej kategorialnej ze zmiennej numerycznej i niestandardowych/przerwanych/jednowartościowych przedziałów czasowych

Na przykład, powiedzmy że posiada data.frame ze zmienną numerycznej df$V i chce utworzyć nową zmienną df$VCAT takie, że:

  • df$VCAT = 0 jeśli df$V jest równe 0
  • df$VCAT = 1 jeśli df$V wynosi od 0 do 10 (tj (0,10))
  • df$VCAT = 2 jest df$V jest równa 10 (tj [10,10]),
  • df$VCAT = 3 oznacza df$V wynosi od 10 do 20 (tj. (10,20))
  • df$VCAT = 4 jest df$V jest większa lub równa niż 20 (czyli [20, Inf])

Jestem obecnie robi to za trudne kodowania funkcję "punktacji" sobie przez robi coś takiego:

df = data.frame(V = seq(1,100)) 
df = df %>% mutate(VCAT = (V>0) + (V==10) + 2*(V>10) (V>=20))` 

Zastanawiam się, czy istnieje prostszy sposób hacky to zrobić w R, najlepiej przy użyciu dplyr (tak, że mogę poleceń łańcucha). Idealnie, szukam krótkiej funkcji, która może być użyta w mutate, która zajmie zmienną V i wektor opisujący zakresy takie jak buckets. Należy pamiętać, że buckets może nie być opisany w najlepszy sposób, ponieważ nie jest dla mnie jasne, w jaki sposób pozwoliłoby użytkownikom na dostosowanie punktów końcowych zakresów.

+2

Czy wiesz o 'cut()'? Sprawdź '? Cut' lub nawet' Hmisc :: cut2() '. – JasonAizkalns

+0

Czy chcesz, aby twoja funkcja pobierała wektor plus 'wiadra' i zwracała ramkę danych, która wygląda jak wynik powyższego? A może chcesz funkcji, która pobiera wektor i 'wiadra' które można przekazać do' mutate'? – jamieRowen

+2

@jamieRowen najlepiej coś, co można przekazać do 'mutate'. –

Odpowiedz

2

Sposób na numery pojemników polega na usunięciu reszty za pomocą modułu opperator, %%. Na przykład. do kosza na grupy 20:

#create raw data 
unbinned<-c(1.1,1.53,5,8.3,33.5,49.22,55,57.9,79.6,81,95,201,213) 
rawdata<-as.data.frame(unbinned) 

#bin the data into groups of 20 
binneddata<-mutate(rawdata,binned=unbinned-unbinned %% 20) 

#print the data 
binneddata 

To daje wynik:

unbinned binned 
1  1.10  0 
2  1.53  0 
3  5.00  0 
4  8.30  0 
5  33.50  20 
6  49.22  40 
7  55.00  40 
8  57.90  40 
9  79.60  60 
10 81.00  80 
11 95.00  80 
12 201.00 200 
13 213.00 200 

więc 0 oznacza 0- < 20, 20 reprezentuje 20- < 40, 40, 60 itd 40- < (oczywiście podzielić wartość binned przez 20, aby uzyskać grup sekwencyjnych jak w pierwotnym pytaniu)

Bonus

Jeśli chcesz użyć wartości zakodowanych jako zmiennych jakościowych w ggplot itd., Konwertując je na łańcuchy, będą one dziwnie zamawiać, np. 200 pojawi się przed 40, ponieważ "2" pojawia się przed "4" w alfabecie, aby ominąć to, użyj funkcji sprintf do stworzenia wiodących zer.(The 3 w %03d powinna być liczba cyfr można oczekiwać najdłuższy numer być):

#convert the data into strings with leading zeros 
binnedstring<-mutate(binneddata,bin_as_character=sprintf('%03d',binned)) 

#print the data 
binnedstring 

dając wyjście:

unbinned binned bin_as_character 
1  1.10  0    000 
2  1.53  0    000 
3  5.00  0    000 
4  8.30  0    000 
5  33.50  20    020 
etc. 

Jeśli chcesz mieć 000-<020, tworzyć górne ograniczenie korzystania arytmetyka i łączyć za pomocą funkcji wklejania:

#make human readable bin value 
binnedstringband<-mutate(
    binnedstring, 
    nextband=binned+20, 
    human_readable=paste(bin_as_character,'-<',sprintf('%03d',nextband),sep='') 
) 

#print the data 
binnedstringband 

Nadanie:

unbinned binned bin_as_character nextband  human_readable 
1  1.10  0    000  20   000-<020 
2  1.53  0    000  20   000-<020 
3  5.00  0    000  20   000-<020 
4  8.30  0    000  20   000-<020 
5  33.50  20    020  40   020-<040 
etc. 
Powiązane problemy