需要一些优化代码的解决方案来运行循环而不使用索引
abc <- data.frame(A = c(1,2,3,4,5) ,
B = c("A","B","C","D","E") ,
C = c("A1" ,"B1" , "A1" , "C1" , "A1") )
让我们说,我想添加一个新的列说D.当且仅当C ==&#34; A1&#34;和A&gt; 2然后D将是1。 所以我的输出需要是:
A B C D
1 1 A A1 NA
2 2 B B1 NA
3 3 C A1 1
4 4 D C1 NA
5 5 E A1 1
可以这样做:
for (i in 1:nrow(abc){
if(abc$C[i] == "A1" & abc$A[i] > 2 )
{
abc$D[i] == 1
}
}
但我希望代码不使用索引来加快处理速度
当我尝试的时候:
if(abc$C == "A1" & abc$A > 2 )
{
abc$D == 1
}
此代码给出错误(仅检查第一行)
然后我尝试了deplyr(mutate)。它工作
abc <- abc %>% mutate( D = ifelse(C == "A1" & A > 2 , 1,NA))
但问题是当我使用函数执行此操作时。假设我有一个功能
test <- function(abc ,abc$A , abc$C){
abc <- abc %>% mutate( D = 1)
return(abc)
}
现在我想在调用它之前使用此函数创建D 在这里输入代码#function我必须检查C和A的条件
所以我尝试了解决方案: 这不起作用。
abc <- abc %>% mutate( if(C == "A1" & A > 2) ) %>% test(abc ,abc$A , abc$C)
我需要解决方案来解决这种类型的场景不像这样
for (i in 1:nrow(abc){
if(abc$C[i] == "A1" & abc$A[i] > 2 )
{
abc <- test(abc ,abc$A , abc$C)
}
}
需要更好的建议。请执行代码并告诉我更好的方法。 我有2000万数据。所以索引会 花很多时间(我想)
答案 0 :(得分:4)
您应该使用data.table框架来加快速度:
require(data.table)
setDT(abc)
abc[C == "A1" & A > 2, D := 1]
答案 1 :(得分:2)
提出的3个解决方案中最快的是data.table
和索引向量(docendo discimus)然后是dplyr
。
f <- function(DF){
DF %>% mutate(D = ifelse(C == "A1" & A > 2 , 1,NA))
}
g <- function(DF){
setDT(DF)
DF[C == "A1" & A > 2, D := 1]
}
h <- function(DF){
idx <- DF[["C"]] == "A1" & DF[["A"]] > 2
DF[["D"]][idx] <- 1
DF
}
set.seed(3472)
n <- 20e6
abcd <- data.frame(
A = sample(5, n, TRUE),
B = sample(c("A","B","C","D","E"), n, TRUE),
C = sample(c("A1", "B1", "A1", "C1", "A1"), n, TRUE)
)
microbenchmark::microbenchmark(
dplyr = {f(abcd)},
data.table = {g(abcd)},
index = {h(abcd)},
times = 10)
Unit: seconds
expr min lq mean median uq max neval
dplyr 5.193977 5.230753 5.299558 5.293965 5.356213 5.419657 10
data.table 1.880420 1.929242 1.976511 1.980238 2.021672 2.089020 10
index 1.866140 1.918988 1.979210 1.956200 2.053038 2.153510 10
请注意,在基于data.table
的解决方案中,重复调用函数setDT()
,在实际情况下使用时,它只会被调用一次。
支持索引向量解决方案,它仅使用基本R而无需加载外部包。
答案 2 :(得分:0)
您的int fd = open("/tmp/testfile", O_CREAT | O_EXCL);
解决方案本身是正确的
dplyr
您不需要跟进功能来检查条件,这是在abc <- abc %>% mutate( D = ifelse(C == "A1" & A > 2 , 1,NA))
如果你真的想把结果传递给另一个函数,你需要删除ifelse
作为第一个函数参数,因为它隐含在abc
之后。
%>%
应该是
... %>% test(abc, arg2, arg3, ...)
答案 3 :(得分:0)
我们可以在函数中传递列名:
abc <- function_name(rlang::sym('column_name1'),rlang::sym('column_name2'))
function_name<- function( var1 , var2)
{
abc <- abc %>%
mutate( C = !!var1,
A = !!var2)
#now everytime we call the function with specific column names the function
#will refer to those column and iterate the values of the column to check
#for any given conditions
abc <- abc %>%
mutate( new_col_D = ifelse(C == "A1" & A > 2 , 1,NA)))
abc <- abc %>% select(-A,-C)
return(abc)
}