2012-10-22 24 views
6

Tôi có danh sách dài các chuỗi như máy tính này có thể đọc được ví dụ:Sử dụng đúng các biểu thức gsub/thông dụng trong R?

A <- list(c("Biology","Cell Biology","Art","Humanities, Multidisciplinary; Psychology, Experimental","Astronomy & Astrophysics; Physics, Particles & Fields","Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods","Geriatrics & Gerontology","Gerontology","Management","Operations Research & Management Science","Computer Science, Artificial Intelligence; Computer Science, Information Systems; Engineering, Electrical & Electronic","Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods; Statistics & Probability")) 

Vì vậy, nó trông như thế này:

> A 
[[1]] 
[1] "Biology" 
[2] "Cell Biology" 
[3] "Art" 
[4] "Humanities, Multidisciplinary; Psychology, Experimental" 
[5] "Astronomy & Astrophysics; Physics, Particles & Fields" 
[6] "Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods" 
[7] "Geriatrics & Gerontology" 
[8] "Gerontology" 
[9] "Management" 
[10] "Operations Research & Management Science" 
[11] "Computer Science, Artificial Intelligence; Computer Science, Information Systems; Engineering, Electrical & Electronic" 
[12] "Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods; Statistics & Probability" 

Tôi muốn chỉnh sửa các điều khoản và loại bỏ các bản sao để có được điều này kết quả:

[1] "Science" 
[2] "Science" 
[3] "Arts & Humanities" 
[4] "Arts & Humanities; Social Sciences" 
[5] "Science" 
[6] "Social Sciences; Science" 
[7] "Science" 
[8] "Social Sciences" 
[9] "Social Sciences" 
[10] "Science" 
[11] "Science" 
[12] "Social Sciences; Science" 

Cho đến nay tôi chỉ nhận điều này:

stringedit <- function(A) 
{ 
    A <-gsub("Biology", "Science", A) 
    A <-gsub("Cell Biology", "Science", A) 
    A <-gsub("Art", "Arts & Humanities", A) 
    A <-gsub("Humanities, Multidisciplinary", "Arts & Humanities", A) 
    A <-gsub("Psychology, Experimental", "Social Sciences", A) 
    A <-gsub("Astronomy & Astrophysics", "Science", A) 
    A <-gsub("Physics, Particles & Fields", "Science", A) 
    A <-gsub("Economics", "Social Sciences", A) 
    A <-gsub("Mathematics", "Science", A) 
    A <-gsub("Mathematics, Applied", "Science", A) 
    A <-gsub("Mathematics, Interdisciplinary Applications", "Science", A) 
    A <-gsub("Social Sciences, Mathematical Methods", "Social Sciences", A) 
    A <-gsub("Geriatrics & Gerontology", "Science", A) 
    A <-gsub("Gerontology", "Social Sciences", A) 
    A <-gsub("Management", "Social Sciences", A) 
    A <-gsub("Operations Research & Management Science", "Science", A) 
    A <-gsub("Computer Science, Artificial Intelligence", "Science", A) 
    A <-gsub("Computer Science, Information Systems", "Science", A) 
    A <-gsub("Engineering, Electrical & Electronic", "Science", A) 
    A <-gsub("Statistics & Probability", "Science", A) 
} 
B <- lapply(A, stringedit) 

Nhưng nó không hoạt động đúng cách:

> B 
[[1]] 
[1] "Science" 
[2] "Cell Science" 
[3] "Arts & Humanities" 
[4] "Arts & Humanities; Social Sciences" 
[5] "Science; Science" 
[6] "Social Sciences; Science, Interdisciplinary Applications; Social Sciences" 
[7] "Science" 
[8] "Social Sciences" 
[9] "Social Sciences" 
[10] "Operations Research & Social Sciences Science" 
[11] "Computer Science, Arts & Humanitiesificial Intelligence; Science; Science" 
[12] "Social Sciences; Science, Interdisciplinary Applications; Social Sciences; Science" 

Làm thế nào tôi có thể đạt được kết quả chính xác nêu trên?
Cảm ơn bạn rất nhiều trước vì đã cân nhắc!

+0

Bất cứ khi nào bạn thấy mình kết thúc bằng nhiều dòng mã tương tự, bạn sẽ bỏ qua [nguyên tắc DRY đáng yêu] (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself). Vì vậy, đó là thời gian để thiết kế lại, rõ ràng là một wrapper thông qua một số loại '* apply'-chức năng, hoặc trợ giúp vòng lặp giống như khác. – aL3xa

Trả lời

4

Hãy để tôi bắt đầu bằng một ví dụ. Bạn có một chuỗi "Cell Biology". Sự thay thế đầu tiên, A <-gsub("Biology", "Science", A), biến nó thành "Khoa học tế bào". Mà sau đó không được thay thế.

Kể từ khi bạn không sử dụng biểu thức thông thường, tôi thà sử dụng một loại một băm để làm thay:

myhash <- c("Science", "Science", "Arts & Humanities", "Arts & Humanities", "Social Sciences", 
    "Science", "Science", "Social Sciences", "Science", "Science", "Science", "Social Sciences", 
    "Science", "Social Sciences", "Social Sciences", "Science", "Science", "Science", "Science", 
    "Science") 

names(myhash) <- c("Biology", "Cell Biology", "Art", "Humanities, Multidisciplinary", 
    "Psychology, Experimental", "Astronomy & Astrophysics", "Physics, Particles & Fields", "Economics", 
    "Mathematics", "Mathematics, Applied", "Mathematics, Interdisciplinary Applications", 
    "Social Sciences, Mathematical Methods", "Geriatrics & Gerontology", "Gerontology", "Management", 
    "Operations Research & Management Science", "Computer Science, Artificial Intelligence", 
    "Computer Science, Information Systems", "Engineering, Electrical & Electronic", 
    "Statistics & Probability") 

Bây giờ, cho một chuỗi như "Sinh học", bạn có thể nhanh chóng tìm kiếm của bạn thể loại:

myhash[ "Biology" ] 

tôi không chắc chắn lý do tại sao bạn muốn sử dụng một danh sách thay vì một vector của chuỗi, do đó tôi sẽ đơn giản hóa một chút trường hợp của bạn:

A <- c("Biology","Cell Biology","Art", 
    "Humanities, Multidisciplinary; Psychology, Experimental", 
    "Astronomy & Astrophysics; Physics, Particles & Fields", 
    "Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods", 
    "Geriatrics & Gerontology","Gerontology","Management","Operations Research & Management Science", 
    "Computer Science, Artificial Intelligence; Computer Science, Information Systems; Engineering, Electrical & Electronic", 
    "Economics; Mathematics, Interdisciplinary Applications; Social Sciences, Mathematical Methods; Statistics & Probability") 

Tra cứu đã không hoạt động đối với các chuỗi tổng hợp (có chứa ";"). Bạn có thể chia chúng, tuy nhiên sử dụng strsplit. Sau đó, bạn có thể sử dụng unique để tránh lặp lại thời hạn và đặt lại với nhau bằng chức năng paste.

stringedit <- function(x) { 
    # first, split into subterms 
    a.all <- unlist(strsplit(x, "; *")) ; 
    paste(unique(myhash[ a.all ]), collapse= "; ") 
} 

unlist(lapply(A, stringedit )) 

Đây là kết quả, như mong muốn:

[1] "Science"       "Science"       "Arts & Humanities"     "Arts & Humanities; Social Sciences" 
[5] "Science"       "Social Sciences; Science"   "Science"       "Social Sciences"     
[9] "Social Sciences"     "Science"       "Science"       "Social Sciences; Science" 

Tất nhiên, bạn có thể gọi *apply nhiều lần như thế:

a.spl <- sapply(A, strsplit, "; *") 
a.spl <- sapply(a.spl, function(x) myhash[ x ]) 
unlist(sapply(a.spl, collapse, "; ") 

Đây không phải là nhiều hay ít hiệu quả hơn so với mã trước. Có, bạn có thể đạt được điều tương tự với biểu thức thông thường, nhưng trước tiên, nó sẽ liên quan đến việc chia chuỗi, sau đó sử dụng regex như ^Biology$ để đảm bảo rằng chúng sẽ khớp với "Sinh học" chứ không phải "Sinh học ô" bạn muốn đi cho các cấu trúc như ". * Sinh học". Cuối cùng, bạn sẽ phải loại bỏ các bản sao anyways, và tất cả nó sẽ là, theo ý kiến ​​của tôi (i) ít tiết hơn (= nhiều lỗi dễ bị) và (ii) không đáng nỗ lực.

+0

IMO, một ý tưởng tồi. Bạn đang 'strsplit'-ing một chuỗi trên mỗi vòng lặp lặp lại. Bạn chỉ nên làm điều đó một lần. – aL3xa

+0

Tôi chỉ có 'strsplit'-ing' length (A) 'số lần; điều này không thực sự khác biệt về số lượng phân tách từ 'lapply (A, strsplit,"; ")'. – January

+0

Cảm ơn bạn rất nhiều vì giải pháp của bạn, @January! – user1496104

2

Và cách sử dụng switch?

science.category <- function(science){ 
    switch(science, 
      "Biology" =, 
      "Cell Biology" =, 
      "Astronomy & Astrophysics" =, 
      "Physics, Particles & Fields" =, 
      "Mathematics" =, 
      "Mathematics, Applied" =, 
      "Mathematics, Interdisciplinary Applications" =, 
      "Geriatrics & Gerontology" =, 
      "Operations Research & Management Science" =, 
      "Computer Science, Artificial Intelligence" =, 
      "Computer Science, Information Systems" =, 
      "Engineering, Electrical & Electronic" =, 
      "Statistics & Probability" = "Science", 
      "Art" =, 
      "Humanities, Multidisciplinary" = "Arts & Humanities", 
      "Psychology, Experimental" =, 
      "Economics" =, 
      "Social Sciences, Mathematical Methods" =, 
      "Gerontology" =, 
      "Management" = "Social Sciences", 
      NA 
      ) 
} 

a <- unlist(lapply(A, strsplit, split = " *; *"), recursive = FALSE) 
a1 <- lapply(a, function(x) unique(sapply(x, science.category))) 
sapply(a1, paste, collapse = "; ") 

Tất nhiên, điều này sẽ hoạt động miễn là bạn có chuỗi thích hợp được đặt trong các đối số switch. Một không khớp và bạn sẽ kết thúc bằng NA. Đối với một số cách sử dụng nâng cao, bạn nên viết trình bao bọc của riêng bạn để sử dụng grep -gia đình chức năng, hoặc thậm chí agrep (xử lý cẩn thận).

+1

Tuy nhiên, bạn bỏ lỡ một cuộc gọi đến 'danh mục khoa học' giữa các cuộc gọi' strsplit' và 'sapply'. – January

+0

Hahahah, tuyệt vời! =) Cảm ơn vì đã phát hiện ra nó! =) – aL3xa

+0

@January, cố định và thnx cho gợi ý. – aL3xa

5

Tôi thấy dễ nhất là có hai cột data.frame làm tra cứu, với một cột cho tên khóa học và một cột cho danh mục. Dưới đây là một ví dụ:

course.categories <- data.frame(
    Course = 
    c("Art", "Humanities, Multidisciplinary", "Biology", "Cell Biology", 
    "Astronomy & Astrophysics", "Physics, Particles & Fields", "Mathematics", 
    "Mathematics, Applied", "Mathematics, Interdisciplinary Applications", 
    "Geriatrics & Gerontology", "Operations Research & Management Science", 
    "Computer Science, Artificial Intelligence", 
    "Computer Science, Information Systems", 
    "Engineering, Electrical & Electronic", "Statistics & Probability", 
    "Psychology, Experimental", "Economics", 
    "Social Sciences, Mathematical Methods", 
    "Gerontology", "Management"), 
    Category = 
    c("Arts & Humanities", "Arts & Humanities", "Science", "Science", 
    "Science", "Science", "Science", "Science", "Science", "Science", 
    "Science", "Science", "Science", "Science", "Science", "Social Sciences", 
    "Social Sciences", "Social Sciences", "Social Sciences", "Social Sciences")) 

Sau đó, giả sử A như một danh sách như trong câu hỏi của bạn:

sapply(strsplit(unlist(A), "; "), 
     function(x) 
     paste(unique(course.categories[match(x, course.categories[["Course"]]), 
             "Category"]), 
       collapse = "; ")) 
# [1] "Science"       "Science"       
# [3] "Arts & Humanities"     "Arts & Humanities; Social Sciences" 
# [5] "Science"       "Social Sciences; Science"   
# [7] "Science"       "Social Sciences"     
# [9] "Social Sciences"     "Science"       
# [11] "Science"       "Social Sciences; Science" 

match phù hợp với các giá trị từ A với tên khóa học trong course.categories bộ dữ liệu và nói mà hàng trận đấu xảy ra trên; điều này được sử dụng để trích xuất danh mục khóa học thuộc về. Sau đó, unique đảm bảo rằng chúng tôi chỉ có một trong mỗi danh mục. paste đặt mọi thứ trở lại với nhau.

+0

Cảm ơn bạn rất nhiều vì gợi ý của bạn, @mrdwab! – user1496104

Các vấn đề liên quan