在R中同时过滤多个条件的数据集的可能性

时间:2019-07-19 19:34:00

标签: r dataset filtering data-manipulation

自5个月以来,我一直是R的热情用户,并且我正在使用R(来自Import,Tidying,Stats,Figures)进行整个研究工作。我有一个带有主键(ID)的数据集。与每个ID关联的是两个因子变量(Factor 1具有三个级别,Factor 2具有两个级别)和一个连续变量(称为Variable)。

所需的data.frame将是以下内容: 像这样的6 ID行的块:

        ID    Factor 1 Factor 2 Variable

1   1003617009  Lev 1   Lev 1   1176.455
2   1003617009  Lev 1   Lev 2   1165.669
3   1003617009  Lev 2   Lev 1   1134.951
4   1003617009  Lev 2   Lev 2   1115.436
5   1003617009  Lev 3   Lev 1   1212.339
6   1003617009  Lev 3   Lev 2   1186.782

也就是说,对于每个IDFactor 1Factor 2Variable,都有一个唯一的组合。原始数据集确实很乱(ID的数量不同(从1到17),每个ID块的因子级别不同,缺少的值等等。

我必须承认:我已经找到了解决我问题的方法。但是代码确实不是很好,我认为它是多余且无效的。我的解决方案如下:

# Import

df_raw <- read_excel("df_raw.xlsx", sheet = 1)

# Selecting relevant columns and deleting nas

df_relevant <- df_raw %>%
  select(ID, Factor1, Factor2, Variable)%>%
  na.omit()

any(is.na(df_relevant))

然后,按块过滤并在不断进行内部联接的同时闭合圆。

df_6 <- df_relevant %>%
  group_by(ID)%>%
  count()%>%
  filter(n == 6)

df_2 <- df_6 %>%
  inner_join(df_relevant, key = "ID")%>%
  group_by(ID, Factor1)%>%
  count()%>%
  filter(n == 2)

df_3 <- df_2 %>%
  inner_join(df_relevant, key = "ID")%>%
  group_by(ID, Factor2)%>%
  count()%>%
  filter(n == 3)

df_final <- df_3 %>%
  inner_join(df_relevant, key = "ID")%>%
  group_by(ID, Factor1, Factor2, Variable)%>%
  count()%>%
  filter(n == 1)%>%
  select(-(n))

这将导致所需的输出。但是,我很确定对于这个特定问题,有一个更优雅的解决方案。

我尝试使用ddply软件包中的plyr,但未成功。然后,尽管我对data.table的可能解决方案进行了很多讨论,但在这里根本没有成功。

对于可能的解决方案的讨论,我感到很高兴。

非常感谢你, 大卫

1 个答案:

答案 0 :(得分:0)

由于连接是通过后续每个连接的输出迭代完成的,因此for循环会很有用

# create a grouping list for each run
grpLst <- list("ID", c("ID", "Factor1"), c("ID", "Factor2"),
         c("ID", "Factor1", "Factor2", "Variable"))
# corresponding filter values
filtVal <- c(6, 2, 3, 1)    

# initialize tmp as the 'df_relevant'
tmp <- df_relevant

# loop through the sequence of 'grpLst'
for(i in seq_along(grpLst)) {
      # join the tmp with df_relevant
      # grouped by the grpLst elements
      # get the frequency count
      # filter the rows based on 'filtVal' elements
      # update the tmp by assignment
      tmp <- tmp %>%              
           inner_join(df_relevant, by = "ID") %>%
           group_by_at(vars(grpLst[[i]])) %>%
           count() %>%
           filter(n == filtVal[i])  



}

df_final <- tmp %>%
              select(-n)