在TRUE / FALSE和NA分组序列中对组进行排名

时间:2019-04-10 06:47:22

标签: r dplyr data.table rank

我有一点要螺母。

我有这样的data.frame

   group criterium
1      A        NA
2      A      TRUE
3      A      TRUE
4      A      TRUE
5      A     FALSE
6      A     FALSE
7      A      TRUE
8      A      TRUE
9      A     FALSE
10     A      TRUE
11     A      TRUE
12     A      TRUE
13     B        NA
14     B     FALSE
15     B      TRUE
16     B      TRUE
17     B      TRUE
18     B     FALSE

structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", 
"B"), class = "factor"), criterium = c(NA, TRUE, TRUE, TRUE, 
FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, NA, FALSE, 
TRUE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA, 
-18L))

我想将TRUE列中的criterium组按升序排列,而忽略FALSENA。目标是在group的每个组中都有一个唯一的组标识符。

所以结果应该像这样:

    group criterium goal
1      A        NA   NA
2      A      TRUE    1
3      A      TRUE    1
4      A      TRUE    1
5      A     FALSE   NA
6      A     FALSE   NA
7      A      TRUE    2
8      A      TRUE    2
9      A     FALSE   NA
10     A      TRUE    3
11     A      TRUE    3
12     A      TRUE    3
13     B        NA   NA
14     B     FALSE   NA
15     B      TRUE    1
16     B      TRUE    1
17     B      TRUE    1
18     B     FALSE   NA

我敢肯定有一种相对简单的方法可以做到这一点,我只是想不到一个。我尝试了dense_rank()dplyr的其他窗口函数,但无济于事。

4 个答案:

答案 0 :(得分:7)

另一种private byte[] zipFiles(ArrayList<File> files, String[] Ids) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos); int count = 0; for (File file : files) { FileInputStream fis = new FileInputStream(file); zos.putNextEntry(new ZipEntry(Ids[count] + "/")); zos.putNextEntry(new ZipEntry(Ids[count] + "/" + file.getName())); while (fis.available() > 0) { zos.write(fis.read()); } zos.closeEntry(); fis.close(); count ++; } zos.flush(); baos.flush(); zos.close(); baos.close(); return baos.toByteArray(); } 方法:

data.table

答案 1 :(得分:6)

也许我对此过于复杂了,但是使用dplyr的一种方法是

library(dplyr)

df %>%
  mutate(temp = replace(criterium, is.na(criterium), FALSE), 
         temp1 = cumsum(!temp)) %>%
   group_by(temp1) %>%
   mutate(goal =  +(row_number() == which.max(temp) & any(temp))) %>%
   group_by(group) %>%
   mutate(goal = ifelse(temp, cumsum(goal), NA)) %>%
   select(-temp, -temp1)

#  group criterium  goal
#   <fct> <lgl>     <int>
# 1 A     NA           NA
# 2 A     TRUE          1
# 3 A     TRUE          1
# 4 A     TRUE          1
# 5 A     FALSE        NA
# 6 A     FALSE        NA
# 7 A     TRUE          2
# 8 A     TRUE          2
# 9 A     FALSE        NA
#10 A     TRUE          3
#11 A     TRUE          3
#12 A     TRUE          3
#13 B     NA           NA
#14 B     FALSE        NA
#15 B     TRUE          1
#16 B     TRUE          1
#17 B     TRUE          1
#18 B     FALSE        NA

我们首先将replace列中的NA criterium移至FALSE,然后求反取的累积总和(temp1)。我们group_by temp1并将1分配给组中的每个第一个TRUE值。最后,按group分组,我们对TRUE值进行累加或对NAFALSE值返回NA

答案 2 :(得分:4)

使用data.table的{​​{1}}选项

rle

逐步

当我们调用library(data.table) DT <- as.data.table(dat) DT[, goal := { r <- rle(replace(criterium, is.na(criterium), FALSE)) r$values <- with(r, cumsum(values) * values) out <- inverse.rle(r) replace(out, out == 0, NA) }, by = group] DT # group criterium goal # 1: A NA NA # 2: A TRUE 1 # 3: A TRUE 1 # 4: A TRUE 1 # 5: A FALSE NA # 6: A FALSE NA # 7: A TRUE 2 # 8: A TRUE 2 # 9: A FALSE NA #10: A TRUE 3 #11: A TRUE 3 #12: A TRUE 3 #13: B NA NA #14: B FALSE NA #15: B TRUE 1 #16: B TRUE 1 #17: B TRUE 1 #18: B FALSE NA 时,我们得到了r <- rle(replace(criterium, is.na(criterium), FALSE))类的对象

rle

我们通过以下方式操作r #Run Length Encoding # lengths: int [1:9] 1 3 2 2 1 3 2 3 1 # values : logi [1:9] FALSE TRUE FALSE TRUE FALSE TRUE ... 内容

values

也就是说,我们用r$values <- with(r, cumsum(values) * values) r #Run Length Encoding # lengths: int [1:9] 1 3 2 2 1 3 2 3 1 # values : int [1:9] 0 1 0 2 0 3 0 4 0 的累积和替换了TRUE,并将values设置为FALSE。现在0返回一个向量,其中inverse.rle将重复values

lenghts

这几乎是OP想要的,但是我们需要将out <- inverse.rle(r) out # [1] 0 1 1 1 0 0 2 2 0 3 3 3 0 0 4 4 4 0 替换为0

NA

对每个replace(out, out == 0, NA) 完成此操作。

数据

group

答案 3 :(得分:4)

一个纯Base R解决方案,我们可以通过return dr; ... textBox1.Text = dr[1].ToString(); 创建一个自定义函数,并按组使用它,即

mesh = build(malla(p2[0],p2[1],angulo1,angulo2)) #1-2
mesh2 = build(malla(p2[1],p2[2],angulo1,angulo2))#2-3
mesh3 = build(malla(p2[2],p2[3],angulo1,angulo2))#3-4
mesh4 = build(malla(p2[3],p2[4],angulo1,angulo2))#4-5
mesh5 = build(malla(p2[4],p2[5],angulo1,angulo2))#5-6

当然,如果需要,您可以通过rle来应用它,即

f1 <- function(x) {
    x[is.na(x)] <- FALSE
    rle1 <- rle(x)
    y <- rle1$values
    rle1$values[!y] <- 0
    rle1$values[y] <- cumsum(rle1$values[y])
    return(inverse.rle(rle1))
}


do.call(rbind, 
     lapply(split(df, df$group), function(i){i$goal <- f1(i$criterium); 
                                             i$goal <- replace(i$goal, is.na(i$criterium)|!i$criterium, NA); 
    i}))

给出,

dplyr