使用apply将R循环转换为函数形式
我已经编写了一些R代码来解析字符串,计算子字符串的出现次数,然后填充子字符串计数表。它工作得很好,但在我使用的实际数据(相当大)上速度非常慢,我知道这是因为我使用的是循环,而不是apply系列的函数。我一直在尝试将此代码转换为函数形式,但我运气不佳,有人能帮我吗?我最大的问题是我无法找到一种方法来使用列名匹配apply构造中的值。下面是一些玩具数据的代码:使用apply将R循环转换为函数形式,r,functional-programming,apply,R,Functional Programming,Apply,我已经编写了一些R代码来解析字符串,计算子字符串的出现次数,然后填充子字符串计数表。它工作得很好,但在我使用的实际数据(相当大)上速度非常慢,我知道这是因为我使用的是循环,而不是apply系列的函数。我一直在尝试将此代码转换为函数形式,但我运气不佳,有人能帮我吗?我最大的问题是我无法找到一种方法来使用列名匹配apply构造中的值。下面是一些玩具数据的代码: #Create toy data, list of unique substrings code_frame<-matrix(c(c(
#Create toy data, list of unique substrings
code_frame<-matrix(c(c('a|a|b|c|d'),c('a|b|b|c|c'),c('a|b|c|d|d')),nrow=3,ncol=1)
all_codes_list<-c('a','b','c','d')
#create data frame with a column for each code and a row for each job
code_count<-as.data.frame(matrix(0, ncol = length(all_codes_list), nrow = nrow(code_frame)))
colnames(code_count)<-all_codes_list
#fill in the code_count data frame with entries where codes occur
for(i in 1:nrow(code_frame)){
test_string<-strsplit(code_frame[i,1],split="|",fixed=TRUE)[[1]]
for(j in test_string){
for(g in 1:ncol(code_count)){
if(j == all_codes_list[g]){
code_count[i,g]<-code_count[i,g]+1
}
}
}
}
#创建玩具数据,唯一子字符串列表
code_frame有一个非常适合这种情况的工具,应该是非常快速和少量的编码,称为mtabulate
:
library(qdap)
mtabulate(strsplit(code_frame, "\\|"))
## a b c d
## 1 2 1 1 1
## 2 1 2 2 0
## 3 1 1 1 2
基本上,它获取向量列表(从strsplit输出)并为每个向量生成一行列表信息
编辑:
如果速度真的是你的事情,那么以下是1000次复制(在Win 7机器上)的基准测试:
和视觉输出:
Abase
备选方案:
df <- read.table(text = code_frame, sep = "|")
tt <- apply(df, 1, function(x){
x2 <- factor(x, levels = letters[1:4])
table(x2)
})
t(tt)
# a b c d
# [1,] 2 1 1 1
# [2,] 1 2 2 0
# [3,] 1 1 1 2
dfA一行,分为三行:
do.call(rbind,
lapply(strsplit(code_frame[,1], "|", fixed=TRUE),
function(x) table(factor(x, levels=all_codes_list))))
请注意,strsplit
是矢量化的,因此不需要在所有行上都使用外部循环。您的内部循环基本上是统计每个代码的出现次数,这是表
的一个应用程序。最后,do.call(rbind,*)
是将行列表转换为单个数据帧的标准习惯用法。这真的是代码帧的样子吗?你如何回答将取决于我给出的建议。是的,基本上。这是一个管道分隔的长字符串,我需要将其分解为子字符串。这不是它的创建方式(它已经从我从中提取它的数据库中形成了一个长管道delim str),但是它的形式是相同的。这很酷。感谢所有的回复,我一定会记住“table”函数。感谢您的mtabulate
函数和计时,+1!
do.call(rbind,
lapply(strsplit(code_frame[,1], "|", fixed=TRUE),
function(x) table(factor(x, levels=all_codes_list))))