计算小于当前值的值数

时间:2018-11-23 16:07:04

标签: r dplyr

如果值小于当前行,我想对 input 列中的行进行计数(请参阅下面的结果)。对我来说,问题是条件是基于当前行值的,因此它与条件为固定数的一般情况有很大不同。

data <- data.frame(input = c(1,1,1,1,2,2,3,5,5,5,5,6))

    input
1      1
2      1
3      1
4      1
5      2
6      2
7      3
8      5
9      5
10     5
11     5
12     6

我期望得到的结果是这样的。例如,对于观测值5和6(值为2),有4个观测值的值1小于其值2。因此, count 的值为4。

    input count
1      1     0
2      1     0
3      1     0
4      1     0
5      2     4
6      2     4
7      3     6
8      5     7
9      5     7
10     5     7
11     5     7
12     6    11

编辑:当我使用dplyr处理分组数据时,我希望获得的最终结果如下所示,也就是说,我希望每个组中的条件都可以动态变化。

data <- data.frame(id = c(1,1,2,2,2,3,3,4,4,4,4,4), 
input = c(1,1,1,1,2,2,3,5,5,5,5,6), 
count=c(0,0,0,0,2,0,1,0,0,0,0,4))

   id input count
1   1     1     0
2   1     1     0
3   2     1     0
4   2     1     0
5   2     2     2
6   3     2     0
7   3     3     1
8   4     5     0
9   4     5     0
10  4     5     0
11  4     5     0
12  4     6     4

3 个答案:

答案 0 :(得分:2)

在基数R中,我们可以使用sapply,并为每个input计算有多少个值大于其自身。

data$count <- sapply(data$input, function(x) sum(x > data$input))

data

#   input count
#1      1     0
#2      1     0
#3      1     0
#4      1     0
#5      2     4
#6      2     4
#7      3     6
#8      5     7
#9      5     7
#10     5     7
#11     5     7
#12     6    11

使用dplyr的一种方法是使用rowwise函数并遵循相同的逻辑。

library(dplyr)

data %>%
  rowwise() %>%
  mutate(count = sum(input > data$input))

答案 1 :(得分:2)

1 outerrowSums

data$count <- with(data, rowSums(outer(input, input, `>`)))

2 tablecumsum

tt <- cumsum(table(data$input))
v <- setNames(c(0, head(tt, -1)), c(head(names(tt), -1), tail(names(tt), 1)))
data$count <- v[match(data$input, names(v))]

3 data.table非等额参加

data.table中使用非等参联接可能会更有效率。计算每次匹配(.N)的行数(by = .EACHI)。

library(data.table)
setDT(data)
data[data, on = .(input < input), .N, by = .EACHI]

如果您的数据按“ id”分组,如在更新中一样,请同时加入该变量:

data[data, on = .(id, input < input), .N, by = .EACHI]

#     id input N
#  1:  1     1 0
#  2:  1     1 0
#  3:  2     1 0
#  4:  2     1 0
#  5:  2     2 2
#  6:  3     2 0
#  7:  3     3 1
#  8:  4     5 0
#  9:  4     5 0
# 10:  4     5 0
# 11:  4     5 0
# 12:  4     6 4

答案 2 :(得分:1)

这里是tidyverse

的一个选项
library(tidyverse)
data %>%
   mutate(count = map_int(input, ~ sum(.x > input))) 
#    input count
#1      1     0
#2      1     0
#3      1     0
#4      1     0
#5      2     4
#6      2     4
#7      3     6
#8      5     7
#9      5     7
#10     5     7
#11     5     7
#12     6    11

更新

使用更新的数据,在上述代码中通过“ id”添加分组

data %>% 
  group_by(id) %>% 
  mutate(count1 = map_int(input, ~ sum(.x > input)))
# A tibble: 12 x 4
# Groups:   id [4]
#      id input count count1
#   <dbl> <dbl> <dbl>  <int>
# 1     1     1     0      0
# 2     1     1     0      0
# 3     2     1     0      0
# 4     2     1     0      0
# 5     2     2     2      2
# 6     3     2     0      0
# 7     3     3     1      1
# 8     4     5     0      0
# 9     4     5     0      0
#10     4     5     0      0
#11     4     5     0      0
#12     4     6     4      4