有效的方法将此函数应用于数据框中的每一行?

时间:2015-09-24 20:16:00

标签: r

我是新编程和R所以如果我在这个问题上不够清楚,我会道歉。我认为我的问题有两个问题。我首先尝试给出一些背景信息。一,我的数据框中有一个数据框:

'data.frame':   27609 obs. of  2 variables:
 $ Diff : num  2557 2038 0 30 0 ...
 $ freq.:'data.frame':  27609 obs. of  1 variable:
  ..$ freq: int  85 68 1 31 1 35 1 1 34 42 ...

> head(d.f.)
  Diff freq
1 2557   85
2 2038   68
3    0    1
4   30   31
5    0    1
6 1034   35

我认为这会导致我的后续问题mapply()在哪里 我想应用一个函数,在每一行中,从一列中取值,除以另一列中的值,然后输出1,2,3或4,具体取决于商所在的值的范围英寸

myFunction = function(a,b) {
    interval = (a/b)
    ifelse(interval==0, 1 ,
           ifelse(interval<1, 2 , 
                  ifelse(interval<31, 3 , 4)))}

Test = mapply(myFunction, d.f.$Diff, d.f.$freq)
> Test
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    3    1    2    1    3
[2,]    4    3    1    2    1    3
[3,]    4    4    1    3    1    4
[4,]    4    4    1    2    1    4
[5,]    4    4    1    3    1    4
[6,]    4    4    1    2    1    3

上面,测试仅在前6行上运行。 最终发生的事情是Test需要永远在整个d.f.运行。并且由于某种原因最终输出矩阵,其中我感兴趣的唯一值在第一行中。我真的很感激帮助我理解我做错了什么。提前谢谢!

3 个答案:

答案 0 :(得分:2)

你的功能是矢量化的:

myFunction(df$Diff, df$freq)
[1] 3 3 1 2 1 3

您可以直接创建新列。

df$newcol <- myFunction(df$Diff, df$freq)

答案 1 :(得分:2)

你在这里重新发明轮子。虽然ifelse是矢量化的,但众所周知它是not the sharpest pencil in drawer。当然,嵌套它们通常是一个坏主意。相反,您具有非常高效的cutfindInterval功能,专门为此类任务而设计。这是一个示例用法

myFunc2 <- function(a, b) {
                     tol <- .Machine$double.eps
                     findInterval(a/b, c(0, 0 + tol, 1, 31 - tol, Inf))
                    }

这里有一些速度比较(你获得x20加速)

set.seed(123)
df <- data.frame(Diff = sample(1e3, 1e8, replace = TRUE),
                 freq = sample(1e2, 1e8, replace = TRUE))


system.time(res <- with(df, myFunction(Diff, freq)))
# user  system elapsed 
# 40.36   18.63  611.18 
system.time(res2 <- with(df, myFunc2(Diff, freq)))
# user  system elapsed 
# 1.89    0.83   76.64 
identical(as.integer(res), res2)
# [1] TRUE

答案 2 :(得分:-1)

如果您将其变为data.table(并调用变量dt):

> dt[, interval := Diff / freq]
> dt[, ifelse(interval == 0, 1, ifelse(interval < 1, 2, ifelse(interval < 31, 3, 4)))]
[1] 3 3 1 2 1 3