2010-12-30 18 views
6

Zaimportowałem dane z pliku do ramki danych w R. To jest coś takiego.Jak dodać kolumnę w ramce danych w R

Name  Count Category 
A   100  Cat1 
C   10  Cat2 
D   40  Cat1 
E   30  Cat3 
H   3  Cat3 
Z   20  Cat2 
M   50  Cat10 

Więc teraz chcę dodać kolumnę Kategoria w zależności od wartości w kolumnie Nazwa. Więc coś takiego jak Nazwa = (A, D), Kategoria = "Cat1" itp.

To tylko prosty przykład, który daję. Mam dużą liczbę nazw i kategorii, więc chcę mieć zwartą składnię. Jak mogę to zrobić?

Edytuj: Zmieniłem przykład, aby lepiej odpowiadał moim potrzebom, ponieważ nazwa może być dowolna, a nie numeryczna. Przepraszam, że nie było to zbyt jasne.

Odpowiedz

2

Możesz korzystać z mapy. (Aktualizacja użyć stringsAsFactors = FALSE)

df <- data.frame(Name = c('A', 'C', 'D', 'E', 'H', 'Z', 'M'), 
        Count = c(100,10,40,30,3,20,50), stringsAsFactors = FALSE) 
Categories <- list(Cat1 = c('A','D'), 
        Cat2 = c('C','Z'), 
        Cat3 = c('E','H'), 
        Cat10 = 'M') 
nams <- names(Categories) 
nums <- sapply(Categories, length) 
CatMap <- unlist(Map(rep, nams, nums)) 
names(CatMap) <- unlist(Categories) 

df <- transform(df, Category = CatMap[ Name ]) 
+0

+1 Przyjemne użycie 'Map()'. To już drugi raz w tygodniu, że ktoś tutaj użył 'Map()' w odpowiedzi i wygląda na to, że jest bardzo przydatny. –

+0

@Gavin dzięki. Właściwie ten drugi post nauczył mnie o Mapie! –

+0

@pchalasani Dzięki temu to dobry sposób na przekodowanie. Jednak próbowałem tego, a mapowanie jest jakoś nie tak, kiedy zrobiłem to w moich rzeczywistych danych. Przykład, który dajesz, działa dobrze. Jakiekolwiek możliwe przyczyny tego? – sfactor

3

Można użyć ifelse. Jeśli ramka danych nazywano df byś zrobił:

df$cat <- ifelse(df$name<100, "Ones", "Hundreds") 
df$cat <- ifelse(df$name<1000, df$cat, "Thousands") 
+0

Przepraszam, że powinienem być bardziej przejrzysty, więc zmieniłem przykład, nazwa może być dowolną wartością alfabetyczną, a nie liczbową. ale dzięki temu postaram się zastosować taką logikę i zobaczyć. – sfactor

2

[Aktualizacja komentarzu op i zmienionym Q]

DF <- data.frame(Name = c("A","C","D","E","H","Z","M"), 
       Count = c(100,10,40,30,3,20,50), stringsAsFactors = FALSE) 
lookup <- data.frame(Name = c("A","C","D","E","H","Z","M"), 
        Category = paste("Cat", c(1,2,1,3,3,2,10), sep = ""), 
        stringsAsFactors = FALSE) 

użyciem powyższych ramek danych, można wykonać scalenie bazie danych. Musisz ustawić lookup dla żądanych kombinacji, co jest w porządku, jeśli nie ma zbyt dużej liczby Name s (Przynajmniej musisz podać je po każdym w lookup i nie musisz zrobić to w porządku - lista wszystkich Cat1Name ów pierwszy, etc):

> merge(DF, lookup, by = "Name") 
    Name Count Category 
1 A 100  Cat1 
2 C 10  Cat2 
3 D 40  Cat1 
4 E 30  Cat3 
5 H  3  Cat3 
6 M 50 Cat10 
7 Z 20  Cat2 
> merge(DF, lookup, by = "Name", sort = FALSE) 
    Name Count Category 
1 A 100  Cat1 
2 C 10  Cat2 
3 D 40  Cat1 
4 E 30  Cat3 
5 H  3  Cat3 
6 Z 20  Cat2 
7 M 50 Cat10 

Jedną z opcji jest indeksowanie:

foo <- function(x) { 
    out <- character(length = length(x)) 
    chars <- c("Ones", "Tens", "Hundreds", "Thousands") 
    out[x < 10] <- chars[1] 
    out[x >= 10 & x < 100] <- chars[2] 
    out[x >= 100 & x < 1000] <- chars[3] 
    out[x >= 1000 & x < 10000] <- chars[4] 
    return(factor(out, levels = chars)) 
} 

alternatywą że skala Lepiej jest,

bar <- function(x, cats = c("Ones", "Tens", "Hundreds", "Thousands")) { 
    out <- cats[floor(log10(x)) + 1] 
    factor(out, levels = cats) 
} 
0

Wyjazd:

  • cut()
  • recode() w pakiecie
0

Może prostsze i bardziej czytelne przy użyciu ifelse i% w% car:

df <- data.frame(Name = c('A', 'C', 'D', 'E', 'H', 'Z', 'M'), 
Count =c(100,10,40,30,3,20,50), stringsAsFactors = FALSE) 

cat1 = c("A","D") 
cat2 = c("C","Z") 
cat3 = c("E","H") 
cat10 = c("M") 

df$Category = ifelse(df$Name %in% cat1, "Cat1", 
       ifelse(df$Name %in% cat2, "Cat2", 
       ifelse(df$Name %in% cat3, "Cat3", 
       ifelse(df$Name %in% cat10, "Cat10", 
       NA)))) 

    Name Count Category 
1 A 100  Cat1 
2 C 10  Cat2 
3 D 40  Cat1 
4 E 30  Cat3 
5 H  3  Cat3 
6 Z 20  Cat2 
7 M 50 Cat10 
Powiązane problemy