簡體   English   中英

在dplyr中基於percent_rank創建組

[英]Create groups based on percent_rank in dplyr

我試圖根據dplyr中某些值的百分比等級創建一些組。

下面的代碼創建一個數據框,然后sapply一個函數來確定組。 缺點是我無法為tbl_postgres工作,只能使用數據幀。 所以我很好奇是否有另一個解決方案。

我曾經考慮過與ntile有關的東西,但我想創建的團體有一些任意的截止。 此外,我沒有太多運氣使用dplyr (也許純sql可能工作)。

library(dplyr)

n <- 100

df1 <- data.frame(idx = 1:n, x = rnorm(n))

df1 <- df1 %>%
            arrange(x) %>%
            mutate(pc_x = percent_rank(x))

index <- function(x) {
    if (x < 0) {
        return(NA)
    } else if (x < 0.3) {
        return(1)
    } else if (x < 0.7) {
        return(2)
    } else if (x <= 1) {
        return(3)
    } else {
        return(NA)
    }
}

df1 <- df1 %>%
            mutate(group = sapply(pc_x, index))

也許cut會滿足您的需求:

library(dplyr)
n <- 100
set.seed(42)
df1 <- data.frame(idx = 1:n, x = rnorm(n))
df1 <- df1 %>%
    arrange(x) %>%
    mutate(pc_x = percent_rank(x))

我在breaks使用-1e9 ,因為cut是“left-open”,所以如果我使用了breaks <- c(0, ...)那么第一行將是NA而不是1。

breaks <- c(-1e9, 0.3, 0.7, 1)
df1 %>%
    mutate(grp = cut(pc_x, breaks=breaks, labels=FALSE)) %>%
    group_by(grp)
## Source: local data frame [100 x 4]
## Groups: grp [3]
##      idx          x       pc_x   grp
##    (int)      (dbl)      (dbl) (int)
## 1     59 -2.9930901 0.00000000     1
## 2     18 -2.6564554 0.01010101     1
## 3     19 -2.4404669 0.02020202     1
## 4     39 -2.4142076 0.03030303     1
## 5     22 -1.7813084 0.04040404     1
## ..   ...        ...        ...   ...

根據您在GitHub上發布的問題 ,根據@joranE和@krlmlr的建議,您可以使用sql()構建自己的自定義SQL查詢:

library(dplyr)
library(microbenchmark)

n <- 100
set.seed(42)
df <- data.frame(idx = 1:10e5, x = rnorm(n))
copy_to(my_db, df, "df")

mbm <- microbenchmark(
joranE = tbl(my_db, sql("
  SELECT x,
    CASE
      WHEN x > 0   AND x <= 0.3 THEN 1
      WHEN x > 0.3 AND x <= 0.6 THEN 2
      WHEN x > 0.6 AND x <= 1   THEN 3
      ELSE NULL
    END
    FROM df")),
krlmlr = tbl(my_db, sql("
  SELECT x,
    CASE
      WHEN x <= 0.3 THEN
        CASE WHEN x <= 0 THEN NULL
        ELSE 1
        END
      ELSE
        CASE WHEN x <= 0.6 THEN 2
        WHEN x <= 1 THEN 3
        ELSE NULL
      END
    END
    FROM df")),
times = 100
)

兩種方法產生類似的結果:

#Unit: milliseconds
#   expr      min       lq     mean   median       uq       max neval cld
# joranE 3.070625 3.118589 3.548202 3.206681 3.307202 30.688142   100   a
# krlmlr 3.058583 3.109567 3.250952 3.205483 3.278453  3.933817   100   a

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM