如何通过R中的两个条件对数据帧进行分组或子集

时间:2018-04-17 13:25:57

标签: r group-by subset

我需要根据两种不同的条件创建数据的子集或组。这是数据结构的样本:

df <- data.frame(id = c("a", "a", "a", "b", "d", "b", "b", "c", "d", "e"),
               kpi = c ("rev", "rev", "rev", "rev", "rev", "fte", "fte", "fte", "fte", "fte"),
               value = c(100, 150, 200, 50, 70, 3, 5, 8, 9, 3))

       id kpi value
    1   a rev   100
    2   a rev   150
    3   a rev   200
    4   b rev    50
    5   d rev    70
    6   b fte     3
    7   b fte     5
    8   c fte     8
    9   d fte     9
    10  e fte     3
  • 第一列填写了公司的ID。每个ID可以有多行,因为它们可能包含多个月的数据(未包含在样本数据中的月份列)以及rev(收入)和fte(全职等效)

  • 的数据
  • 我想选择在某个范围内fte平均值的每家公司:1-5

    • 例如公司b应该被包括在内,因为它的平均fte为4(在另一个5中的一个月3中),公司d应该被排除,因为它具有更高的fte。
  • 对于那些我希望所有行保留在数据框中,因此也是那些具有rev数据的行。目标是计算具有特定fte数的公司群组的平均收入。

具有上述条件的new.data框架对于样本数据应如下所示:

 df <- data.frame(id = c("b", "b", "b", "e"),
               kpi = c("rev", "fte", "fte", "fte"), value = c(50, 3, 5, 3))

      id kpi value
    1  b rev    50
    2  b fte     3
    3  b fte     5
    4  e fte     3

它将应用于大约40,000行的data.frame。

我已经做过一些研究,发现很多关于创建具有多个条件的子集,但我无法应用于我的具体问题。如果这是一个显而易见的问题,我很抱歉,我是R新秀,可以真正使用一些帮助!

如果我没有明确说明问题,请随时提出,我会尽力解释清楚!

提前谢谢大家!

4 个答案:

答案 0 :(得分:3)

对id进行分组,然后过滤满足条件的那些:

library(dplyr)

df %>% 
   group_by(id) %>%
   filter(between(mean(value[kpi == "fte"]), 1, 5)) %>%
   ungroup

,并提供:

# A tibble: 4 x 3
  id    kpi   value
  <fct> <fct> <dbl>
1 b     rev     50.
2 b     fte      3.
3 b     fte      5.
4 e     fte      3.

答案 1 :(得分:1)

在基础R中,您可以使用ave创建临时变量,然后使用该变量。

a <- ave(df$value, df$id, df$kpi, FUN = mean)
new <- df[1 <= a & a <= 5, ]
new
#   id kpi value
#6   b fte     3
#7   b fte     5
#10  e fte     3

现在删除不再需要的内容。

rm(a)    # clean up

答案 2 :(得分:0)

您可以尝试tidyverse解决方案

library(tidyverse)
df %>%
  group_by(id,kpi) %>% 
  mutate(Mean=mean(value)) %>% 
  mutate(gr= between(Mean, 1, 5)) %>% 
  group_by(id) %>% 
  mutate(gr2 = ifelse(any(gr) & kpi == "rev",T, F)) %>% 
  filter(gr | gr2) %>% 
  select(1:3)
# A tibble: 4 x 3
# Groups:   id [2]
  id    kpi   value
  <fct> <fct> <dbl>
1 b     rev     50.
2 b     fte      3.
3 b     fte      5.
4 e     fte      3.

我列出了每个步骤来说明这个想法是什么。

  1. 首先计算每个idkpi值的均值。
  2. 如果平均值介于1到5之间,请添加TRUE
  3. 再次按ID分组以过滤相应的rev
  4. 过滤器
  5. 选择正确的列。

答案 3 :(得分:0)

以下是data.table的解决方案:

library("data.table")
setDT(df)
df[df[kpi=="fte", if (between(mean(value), 1, 5)) id, id], on="id"][, -c("V1")]
# > df[df[kpi=="fte", if (between(mean(value), 1, 5)) id, id], on="id"][, -c("V1")]
#    id kpi value
# 1:  b rev    50
# 2:  b fte     3
# 3:  b fte     5
# 4:  e fte     3

df[df[kpi=="fte", if (between(mean(value), 1, 5)) id, id][,-2], on="id"][]