如何按照R中的国会图书馆分类(LCC)编号进行排序

时间:2017-07-21 14:33:27

标签: r sorting

美国国会图书馆在图书馆中使用分类编号来为事物提供电话号码,以便在货架上订购。它们可以是简单的也可以是非常复杂的,有一些强制性部分但很多是可选的。 (请参阅050 Library of Congress Call Number上的“050中的电话号码”以了解它们如何分解,或lc_callnumber查看对其进行分类的Ruby工具。)

我想按照R中的LCC编号排序。我看过Sort a list of nontrivial elements in RSorting list of list of elements of a custom class in R?,但还没弄明白。

以下是四个电话号码,按排序顺序输入:

call_numbers <- c("QA 7 H3 1992", "QA 76.73 R3 W53 2015", "QA 90 H33 2016", "QA 276.45 R3 A35 2010")

sort按字符排序,所以276&lt; 7&lt; 76.73&lt; 90。

> sort(call_numbers)
[1] "QA 276.45 R3 A35 2010" "QA 7 H3 1992"          "QA 76.73 R3 W53 2015"  "QA 90 H33 2016"       

要对它们进行正确排序,我认为我必须定义一个类,然后在其上定义一些方法,如下所示:

library(stringr)
class(call_numbers) <- "LCC"

## Just pick out the letters and digits for now, leave the rest
## until sorting works, then work down more levels.
lcc_regex <- '([[:alpha:]]+?) ([[:digit:]\\.]+?) (.*)'

"<.LCC" <- function(x, y) {
    x_lcc <- str_match(x, lcc_regex)
    y_lcc <- str_match(y, lcc_regex)
    if(x_lcc[2] < y_lcc[2]) return(x)
    if(as.integer(x_lcc[3]) < as.integer(y_lcc[3])) return(x)
}
"==.LCC" <- function(x, y) {
    x_lcc <- str_match(x, lcc_regex)
    y_lcc <- str_match(y, lcc_regex)
    x_lcc[2] == y_lcc[2] && x_lcc[3] == y_lcc[3]
}

">.LCC" <- function(x, y) {
    x_lcc <- str_match(x, lcc_regex)
    y_lcc <- str_match(y, lcc_regex)
    if(x_lcc[2] > y_lcc[2]) return(x)
    if(as.integer(x_lcc[3]) > as.integer(y_lcc[3])) return(x)
}

这不会改变排序顺序。我没有定义子集方法("[.myclass"),因为我不知道它应该是什么。

4 个答案:

答案 0 :(得分:1)

这可能是一种更简单的方法。这假设每个数字都具有以下格式:2个字母的代码,空格,数字,空格,字母数字,空格......年份。

策略是两个用空格分割LOC数,然后获得前三个字段的3列数据,然后每个列可以用order函数顺序排序。

call_numbers <- c("QA 7 H3 1992", "QA 76.73 R3 W53 2015", "QA 90 H33 2016", "QA 276.45 R3 A35 2010")

#split on the spaces
 split<-strsplit(call_numbers, " " )
#Retrieve the 2 letter code
 letters<-sapply(split, function(x){x[1]})
#retrieve the 2nd number group and convert to numeric values for sorting
 second<-sapply(split, function(x){as.numeric(x[2])})
#obtain the 3rd grouping
 third<-sapply(split, function(x){x[3]})
#find the year
 year<-sapply(split, function(x){x[length(x)]})

df<-data.frame(call_numbers)
#sort data based on the first and 2nd column
call_numbers[order(letters, second, third)]

对于这个有限的数据集,该技术可行。

答案 1 :(得分:1)

来自mixedsort包(标准R的一部分)的

gtools证明了这一点:

library(gtools)
call_numbers <- c("QA 7 H3 1992", "QA 76.73 R3 W53 2015", "QA 90 H33 2016", "QA 276.45 R3 A35 2010")
mixedsort(call_numbers)
## [1] "QA 7 H3 1992"          "QA 76.73 R3 W53 2015"  "QA 90 H33 2016"        "QA 276.45 R3 A35 2010"

此外,mixedorder可用于按一列对数据框进行排序。

这是前面How to sort a character vector where elements contain letters and numbers in R?

中回答的特例

答案 2 :(得分:0)

我觉得我花了太多时间来确定一个解决方案,以确定你正在尝试做什么 - 只有我的是JavaScript。但它基本上归结为&#34;规范化&#34;这些数字可以按字母顺序排序。

也许这个解决方案可以使用并移植到R.至少,希望这可以让你开始。它涉及一些正则表达式和一些额外的脚本,以使电话号码进入可以进行排序的状态。

https://github.com/rayvoelker/js-loc-callnumbers/blob/master/locCallClass.js

祝你好运!

答案 3 :(得分:0)

最简单(又优雅)的方法:使用str_sort包中的stringr

# install.packages("stringr") ## Uncomment if not already installed
library(stringr)

str_sort(call_numbers, numeric = TRUE)

[1] "QA 7 H3 1992"          "QA 76.73 R3 W53 2015"  "QA 90 H33 2016"       
[4] "QA 276.45 R3 A35 2010"