在一个数据帧中添加一个计数列,其中包含另一个数据帧中的匹配计数

时间:2012-12-06 22:19:22

标签: r dataframe

我想在数据框中添加一个列,其中包含另一个数据框中的匹配数,这看起来非常简单,但我似乎无法让它工作。例如:

smaller_df$CountOfMatches <- nrow(subset(larger_df, Date == smaller_df$Date))

这给了我错误:

In `==.default`(Date, smaller_df$Date) :
  longer object length is not a multiple of shorter object length

我知道数据框的长度不同,我不是要求合并,我只需要在smaller_df中的每一行/日期(有效日期对象);计算greater_df中的匹配数。

我对R来说很新,所以我必须有一些基本的,非常微不足道的东西。

提前致谢

3 个答案:

答案 0 :(得分:4)

最简单的方法是创建一个摘要表,然后将其与原始(较小的)数据合并。最好有一个可重复的例子。所以这里有一些可重复的数据:

smaller_df <- data.frame(Date=seq(as.Date("2000-01-01"), 
                                  as.Date("2000-01-10"), by="1 day"))
set.seed(5)
larger_df <- data.frame(Date=sample(seq(as.Date("2000-01-01"), 
                                        as.Date("2000-01-20"), by="1 day"),
                                    80, replace=TRUE))

larger_df

中创建日期表(计数)
tbl <- table(larger_df$Date)

将其转换为适合合并的data.frame

counts <- data.frame(Date=as.Date(names(tbl)), CountOfMatches=as.vector(tbl))

然后在日期合并。请注意,如果日期未显示在larger_df中,但会显示在smaller_df中,那么CountOfMatches将是NA而不是0

merge(smaller_df, counts, all.x=TRUE)

对于此示例数据,您将获得

> merge(smaller_df, counts, all.x=TRUE)
         Date CountOfMatches
1  2000-01-01              4
2  2000-01-02              2
3  2000-01-03              5
4  2000-01-04              4
5  2000-01-05              5
6  2000-01-06              6
7  2000-01-07              2
8  2000-01-08              5
9  2000-01-09              3
10 2000-01-10              3

编辑:

使用包的一个更简洁的版本(它提供了摆脱一些转换细节的便利功能)是

library("plyr")
merge(smaller_df, 
      ddply(larger_df, .(Date), summarise, CountOfMatches=length(Date)),
      all.x = TRUE)

相同的结果,实际上是相同的逻辑。关于larger_df中没有出现的日期,也有同样的警告。

答案 1 :(得分:4)

有一种方法可以使用data.table包来完成此操作。这是一个用于在内存中有效处理大型数据集的包,允许类似SQL或SAS数据的步骤式操作,但方括号[]的行为与data.frame对象不同。您可以在[]中放入data.table连接,表达式和聚合。阅读data.table手册以了解更多信息。

首先,将两个帧转换为data.table对象,并将键列设置为Date。 data.table对象将按日期排序,然后可以加入。

使用与上述相同的样本数据:

library(data.table)
smaller_df <- data.table(data.frame(Date=seq(as.Date("2000-01-01"), 
    as.Date("2000-01-10"), by="1 day")))
set.seed(5)
larger_df <- data.table(data.frame(Date=sample(seq(as.Date("2000-01-01"), 
    as.Date("2000-01-20"), by="1 day"), 80, replace=TRUE)))

将键列设置为Date:

setkey(smaller_df, Date)
setkey(larger_df, Date)

您可以使用by-without-by语法并使用您按日期键入的事实。 .N将返回子集中的行数(即日期匹配的行数)。

larger_df[smaller_df, .N]
##         Date   N
##  1: 2000-01-01 4
##  2: 2000-01-02 2
##  3: 2000-01-03 5
##  4: 2000-01-04 4
##  5: 2000-01-05 5
##  6: 2000-01-06 6
##  7: 2000-01-07 2
##  8: 2000-01-08 5
##  9: 2000-01-09 3
## 10: 2000-01-10 3

答案 2 :(得分:4)

这似乎相当简单:

smaller_df$bigDfCount <-sapply( smaller_df$Date,  
                        FUN=function(x) length(larger_df[larger_df$Date==x, "Date"] ) )
smaller_df

         Date bigDfCount
1  2000-01-01          4
2  2000-01-02          2
3  2000-01-03          5
4  2000-01-04          4
5  2000-01-05          5
6  2000-01-06          6
7  2000-01-07          2
8  2000-01-08          5
9  2000-01-09          3
10 2000-01-10          3