2010-12-30 38 views
6

Tôi đã nhập dữ liệu từ một tệp vào một khung dữ liệu trong R. Nó giống như thế này.Làm thế nào để thêm một cột trong một khung dữ liệu trong 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 

Vì vậy, bây giờ tôi muốn thêm cột Thể loại tùy thuộc vào các giá trị trong cột Tên. Vì vậy, một cái gì đó như nếu Tên = (A, D), Thể loại = 'Cat1' vv

Đây chỉ là một ví dụ đơn giản tôi đang đưa ra. Tôi có một số lượng lớn Tên và Danh mục nên tôi muốn có một cú pháp nhỏ gọn. Tôi có thể làm cái này như thế nào?

Chỉnh sửa: Tôi đã thay đổi ví dụ để phù hợp hơn với nhu cầu của tôi vì tên có thể là bất kỳ thứ gì không phải là số. Xin lỗi vì không quá rõ ràng trước đây.

Trả lời

2

Bạn có thể sử dụng bản đồ. (CẬP NHẬT sử dụng 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 Sử dụng tốt nhất 'Bản đồ()'. Đây là lần thứ hai trong một tuần, một người nào đó ở đây đã sử dụng 'Map()' trong một câu trả lời và họ thực sự rất hữu ích. –

+0

@Gavin cảm ơn. Trên thực tế, bài đăng khác đã dạy tôi về Bản đồ! –

+0

@pchalasani Cảm ơn đây là một cách hay để thực hiện việc ghi lại. Tuy nhiên tôi đã thử điều này và ánh xạ là tất cả sai bằng cách nào đó khi tôi đã làm nó trong dữ liệu thực tế của tôi. Ví dụ bạn cung cấp cho các công trình tốt. Bất kỳ lý do có thể cho điều này? – sfactor

3

Bạn có thể sử dụng ifelse. Nếu khung dữ liệu của bạn được gọi là df bạn sẽ làm gì:

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

xin lỗi tôi nên rõ ràng hơn, vì vậy tôi đã thay đổi ví dụ, tên có thể là bất kỳ giá trị chữ cái nào không phải là số. nhưng cảm ơn tôi sẽ cố gắng áp dụng một logic như thế này và xem. – sfactor

2

[Cập nhật sau bình luận của OP và thay đổi 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) 

Sử dụng các khung dữ liệu trên, chúng ta có thể làm việc kết hợp với cơ sở dữ liệu. Bạn cần phải thiết lập lookup cho số NameCategory kết hợp bạn muốn, điều này là OK nếu không có số lượng lớn Name s (Ít nhất bạn chỉ cần liệt kê chúng một lần trong mỗi số lookup và bạn không phải làm điều đó trong trật tự - liệt kê tất cả Cat1Name đầu tiên, vv):

> 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 

Một lựa chọn là lập chỉ mục:

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)) 
} 

Một thay thế mà quy mô Tốt hơn là,

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

check out:

  • cut()
  • recode() trong car gói
0

Có lẽ đơn giản hơn và dễ đọc hơn bằng ifelse và% theo%:

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 
Các vấn đề liên quan