【问题标题】:Make a range of ID's based on sum of values in R根据R中值的总和制作一系列ID
【发布时间】:2017-10-07 09:09:25
【问题描述】:

对r不太熟悉,不知道这是不是一个简单的问题。 我想根据它们占总和的 60%(或大约)的值的总和来创建一系列 ID。这是数据框。 DF

ID     Val
98     2
98     1
98     4
3     11
3      6
3      8
3      1
24     3
24     2
46     1
46     2
59     6

这样我会首先按 ID 对 DF 进行排序,然后检查哪个 ID 范围的值总和高达 60% 并将它们分组,其余的按 10%、10%、10%、10% 分组(或者它可以是随机的 10%、10%、20% 或 5%、15%、10%、10%)。这样我的数据框看起来像

ID     Val
3-24   35           # (11+6+8+1+3+2) ~ 62% of the total sum of `Val` column
46-59  9            # (1+2+6) = 18% of the total sum of `Val` column
98     7            # (2+1+4) =14% of the total sum of `Val` column

我可以试试这个

DF=DF[with(DF, order(DF$ID)), ]
perce = round(sum(DF$ID)*60/100)
for(i in 1:dim(DF)[1]){
     if(sum(DF$Val) == perce){
      ID=which(DF$ID)
       .
       .
       .
put those ID's in a range that constitutes 60%

       }
    }

我不知道这是否可能。?

谢谢 多尼克

【问题讨论】:

  • 看起来你正在测试浮点数是否相等 DF$Val == perce;这可能会导致问题;另外,?cut 可能会有所帮助
  • @cumin 求和并四舍五入perce
  • 我不确定您到底在寻找什么,但您查看过ntile function 吗?
  • 不,不能从中得到太多

标签: r for-loop if-statement dataframe cumsum


【解决方案1】:

首先,我们对数据进行排序,得到每个ID-group的sum

然后我们可以使用cumsum(Val) 来获取运行总数。我们需要lag this 所以它代表“这一行之前所有ID-group 的值的总和”。

现在,我们可以使用cut 将累积和分配给区间组(-∞, 0.6 * total](0.7 * total, 0.8 * total](0.8 * total, ∞)

那么我们可以group_by这个区间得到Valsum

library('tidyverse')

df <- tribble(
  ~ID, ~Val,
   98,    2,
   98,    1,
   98,    4,
    3,    11,
    3,    6,
    3,    8,
    3,    1,
   24,    3,
   24,    2,
   46,    1,
   46,    2,
   59,    6
)

breaks_proportions <- c(0.6, 0.1, 0.1)
breaks_values <- cumsum(breaks_proportions) * sum(df$Val)

df %>%
  arrange(ID) %>%
  group_by(ID) %>%
  summarise(Val = sum(Val)) %>%
  mutate(
    running_total = lag(cumsum(Val), default = 0),
    group = cut(
      running_total,
      c(-Inf, breaks_values, Inf))) %>%
  group_by(group) %>%
  summarise(
    ID = stringr::str_c(min(ID), '-', max(ID)),
    Val = sum(Val)) %>%
  select(ID, Val)
# # A tibble: 4 x 2
#      ID   Val
#   <chr> <dbl>
# 1  3-24    31
# 2 46-46     3
# 3 59-59     6
# 4 98-98     7

【讨论】:

  • 看来您已将breaks_proportions 设为 60%、10% 和 10%,其余 20% 或其他逻辑呢?如果你能解释一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多