R:可行的快速(条件)子集

时间:2019-08-09 12:49:13

标签: r data.table subset

我想对数据行进行子集

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 53204
EXPOSE 44391

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ["Versandformulartool/Versandformulartool.csproj", "Versandformulartool/"]
RUN dotnet restore "Versandformulartool/Versandformulartool.csproj"
COPY . .
WORKDIR "/src/Versandformulartool"
RUN dotnet build "Versandformulartool.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "Versandformulartool.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Versandformulartool.dll"]

分几个阶段。我知道我可以顺序应用query = '''SELECT * FROM "TABLE" WHERE ts_date::date = date '2019-06-19' ''' query = '''SELECT * FROM "TABLE" WHERE ts_date::date = '2019-06-19' ''' 来实现这一目标。

library(data.table); set.seed(333); n <- 100
dat <- data.table(id=1:n, x=runif(n,100,120), y=runif(n,200,220), z=runif(n,300,320))

> head(dat)
   id        x        y        z
1:  1 109.3400 208.6732 308.7595
2:  2 101.6920 201.0989 310.1080
3:  3 119.4697 217.8550 313.9384
4:  4 111.4261 205.2945 317.3651
5:  5 100.4024 212.2826 305.1375
6:  6 114.4711 203.6988 319.4913

我的问题是我需要使它自动化,并且子集为空可能会发生。在这种情况下,我想跳过导致空集的步骤。例如,如果我的数据是

subset(.)

第二步> s <- subset(dat, x>119) > s <- subset(s, y>219) > subset(s, z>315) id x y z 1: 55 119.2634 219.0044 315.6556 将变成空白,但我仍然想应用第三步dat2 <- dat[1:50] > s <-subset(dat2,x>119) > s id x y z 1: 3 119.4697 217.8550 313.9384 2: 50 119.2519 214.2517 318.8567 。是否只有在产生非空集的情况下才应用子命令的方法?我想象像subset(s, y>219)之类的东西。我想避免像

这样的构造
subset(s,z>315)

因为我担心if-then丛林会相当慢,特别是因为我需要使用subset(s, y>219, nonzero=TRUE)将所有这些都应用于列表中的不同data.tables。这就是为什么我希望找到针对速度进行优化的解决方案。

PS。为了清楚起见,我仅选择s <- dat if(nrow(subset(s, x>119))>0){s <- subset(s, x>119)} if(nrow(subset(s, y>219))>0){s <- subset(s, y>219)} if(nrow(subset(s, z>318))>0){s <- subset(s, z>319)} ,例如如果不是,那么data.table将同样受欢迎。

2 个答案:

答案 0 :(得分:4)

我同意Konrad的回答,即应该发出警告或至少报告以某种方式发生的情况。这是一种利用索引的data.table方法(有关详细信息,请参见程序包小插图):

f = function(x, ..., verbose=FALSE){
  L   = substitute(list(...))[-1]
  mon = data.table(cond = as.character(L))[, skip := FALSE]

  for (i in seq_along(L)){
    d = eval( substitute(x[cond, verbose=v], list(cond = L[[i]], v = verbose)) )
    if (nrow(d)){
      x = d
    } else {
      mon[i, skip := TRUE]
    }    
  }
  print(mon)
  return(x)
}

用法

> f(dat, x > 119, y > 219, y > 1e6)
        cond  skip
1:   x > 119 FALSE
2:   y > 219 FALSE
3: y > 1e+06  TRUE
   id        x        y        z
1: 55 119.2634 219.0044 315.6556

verbose选项将打印由data.table包提供的额外信息,因此您可以查看何时使用索引。例如,使用f(dat, x == 119, verbose=TRUE),我看到了。

  

因为我担心if-then丛林会相当慢,尤其是因为我需要使用lapply(。)将所有这些都应用于列表中的不同data.tables。

如果用于非交互使用,使函数返回list(mon = mon, x = x)可能更好,以便更轻松地跟踪查询的内容和发生的情况。此外,可以捕获并返回详细的控制台输出。

答案 1 :(得分:3)

可以使用filter中提供的修改后的dplyr函数来开发一种有趣的方法。如果不满足条件,则non_empty_filter过滤器函数将返回原始数据集。

注释

  • 恕我直言,这是相当不规范的行为,应通过warning报告。当然,可以将其删除,并且与功能结果无关。

功能

library(tidyverse)
library(rlang) # enquo
non_empty_filter <- function(df, expr) {
    expr <- enquo(expr)

    res <- df %>% filter(!!expr)

    if (nrow(res) > 0) {
        return(res)
    } else {
        # Indicate that filter is not applied
        warning("No rows meeting conditon")
        return(df)
    }
}

满足条件

行为:返回满足条件的一行。

dat %>%
    non_empty_filter(x > 119 & y > 219)

结果

# id        x        y        z
# 1 55 119.2634 219.0044 315.6556

不符合条件

行为:由于y > 1e6,无法满足全部条件,无法返回完整的数据集。

dat %>%
    non_empty_filter(x > 119 & y > 219 & y > 1e6)

结果

# id        x        y        z
# 1:   1 109.3400 208.6732 308.7595
# 2:   2 101.6920 201.0989 310.1080
# 3:   3 119.4697 217.8550 313.9384
# 4:   4 111.4261 205.2945 317.3651
# 5:   5 100.4024 212.2826 305.1375
# 6:   6 114.4711 203.6988 319.4913
# 7:   7 112.1879 209.5716 319.6732
# 8:   8 106.1344 202.2453 312.9427
# 9:   9 101.2702 210.5923 309.2864
# 10:  10 106.1071 211.8266 301.0645

条件一次/一次不满足

行为:跳过过滤器,该过滤器将返回一个空数据集。

dat %>%
    non_empty_filter(y > 1e6) %>% 
    non_empty_filter(x > 119) %>% 
    non_empty_filter(y > 219)

结果

# id        x        y        z
# 1 55 119.2634 219.0044 315.6556