编辑数据帧以创建配对样本;删除另一组中没有匹配日期的记录

时间:2014-05-01 15:19:24

标签: r dataframe match

我已经做了很多寻找解决方案,并且当我看到它时,要么找不到,要么就不知道。我已经看到了一些与此相近的主题,但处理了两个不同数据帧之间的匹配,而这只涉及单个数据帧。

我有一个包含两个组(因子,col1)和一个采样日期(日期,col2)的数据框,然后是测量(数字,col3)。我想最终对A组和B组之间的配对样本进行统计测试,因此为了创建配对样本,我想只保留两组在同一天进行测量的记录。换句话说,删除组A中没有在组B中的同一天进行相应测量的记录,反之亦然。在下面的示例数据中,这将导致删除第4行和第8行。另一种思考方式是,如何搜索和删除每个日期只出现一次的记录?

示例数据:

my.df <- data.frame(col1 = as.factor(c(rep("A", 4), rep("B", 4))),
                    col2 = as.Date(c("2001-01-01", "2001-01-02", "2001-01-03",
                    "2001-01-04", "2001-01-01", "2001-01-02", "2001-01-03", 
                    "2001-02-03")), 
                    col3 = sample(8))

1 个答案:

答案 0 :(得分:3)

以下是一些替代方案:

1)ave

> subset(my.df, ave(col3, col2, FUN = length) > 1)
  col1       col2 col3
1    A 2001-01-01    3
2    A 2001-01-02    2
3    A 2001-01-03    6
5    B 2001-01-01    7
6    B 2001-01-02    4
7    B 2001-01-03    1

2)split / Filter / do.call

> do.call("rbind", Filter(function(x) nrow(x) > 1, split(my.df, my.df$col2)))
             col1       col2 col3
2001-01-01.1    A 2001-01-01    3
2001-01-01.5    B 2001-01-01    7
2001-01-02.2    A 2001-01-02    2
2001-01-02.6    B 2001-01-02    4
2001-01-03.3    A 2001-01-03    6
2001-01-03.7    B 2001-01-03    1

3)dplyr (2)几乎直接翻译成dplyr解决方案:

> library(dplyr)
> my.df %>% group_by(col2) %>% filter(n() > 1)
Source: local data frame [6 x 3]
Groups: col2

  col1       col2 col3
1    A 2001-01-01    5
2    A 2001-01-02    1
3    A 2001-01-03    7
4    B 2001-01-01    2
5    B 2001-01-02    4
6    B 2001-01-03    6

4)data.table 最后两个解决方案也可以转换为data.table

> data.table(my.df)[, if (.N > 1) .SD, by = col2]
         col2 col1 col3
1: 2001-01-01    A    5
2: 2001-01-01    B    2
3: 2001-01-02    A    1
4: 2001-01-02    B    4
5: 2001-01-03    A    7
6: 2001-01-03    B    6

5)tapply

> na.omit(tapply(my.df$col3, my.df[c('col2', 'col1')], identity))
            col1
col2         A B
  2001-01-01 3 7
  2001-01-02 2 4
  2001-01-03 6 1
attr(,"na.action")
2001-02-03 2001-01-04 
         5          4 

6)合并

> merge(subset(my.df, col1 == 'A'), subset(my.df, col1 == 'B'), by = 2)
        col2 col1.x col3.x col1.y col3.y
1 2001-01-01      A      3      B      7
2 2001-01-02      A      2      B      4
3 2001-01-03      A      6      B      1

7)sqldf (6)类似于以下sqldf解决方案:

> sqldf("select * from `my.df` A join `my.df` B 
+    on A.col2 = B.col2 and A.col1 = 'A' and B.col1 = 'B'")
  col1       col2 col3 col1       col2 col3
1    A 2001-01-01    5    B 2001-01-01    2
2    A 2001-01-02    1    B 2001-01-02    4
3    A 2001-01-03    7    B 2001-01-03    6