我有一个包含重复记录/公共记录的数据集。它看起来像这样:
| Vendor | Buyer | Amount |
|--------|:-----:|-------:|
| A | P | 100 |
| B | P | 150 |
| C | Q | 300 |
| A | P | 290 |
我需要将类似的记录分组在一起,但我不想总结我的金额。我想单独表示金额值。输出应如下所示:
| Vendor | Buyer | Amount |
|--------|:-----:|-------:|
| A | P | 100 |
| A | P | 290 |
| | | |
| B | P | 150 |
| | | |
| C | Q | 300 |
我想使用 split((,但由于我的原始数据有太多记录,split 函数会创建太多列表,从它们创建新数据集变得乏味。如何使用任何其他方法实现上述输出?
编辑:让我们假设我们有一个名为 date 的附加列,数据集现在如下所示:
| Vendor | Buyer | Amount | Date |
|--------|:-----:|-------:|-----------|
| A | P | 100 | 3/6/2019 |
| B | P | 150 | 7/6/2018 |
| C | Q | 300 | 4/21/2018 |
| A | P | 290 | 6/5/2018 |
一旦,每个买家和供应商都分组在一起,我需要按升序排列每个买家和供应商的日期,使其看起来像下面这样:
| Vendor | Buyer | Amount | Date |
|--------|:-----:|-------:|-----------|
| A | P | 290 | 6/5/2018 |
| A | P | 100 | 3/6/2019 |
| | | | |
| B | P | 150 | 7/6/2018 |
| | | | |
| C | Q | 300 | 4/21/2018 |
然后删除单个事务以获取仅包含的最终表
| Vendor | Buyer | Amount | Date |
|--------|:-----:|-------:|----------|
| A | P | 290 | 6/5/2018 |
| A | P | 100 | 3/6/2019 |
在下文中,我们对数据框进行排序并添加一个组列,以便对单个组进行轻松的后续处理。 例如,要在不创建大量DF
的情况下处理组:
for(g in unique(DFout$group)) {
DFsub <- subset(DFout, group == g)
... process DFsub ...
}
1( 基本 R 对数据进行排序,然后使用对非重复元素的cumsum
分配组列。
library(data.table)
o <- with(DF, order(Vendor, Buyer))
DFo <- DF[o, ]
DFout <- transform(DFo, group = cumsum(!duplicated(data.frame(Vendor, Buyer))))
DFout
给:
Vendor Buyer Amount group
1 A P 100 1
4 A P 290 1
2 B P 150 2
3 C Q 300 3
我不确定这首先是一个好主意,但如果您真的想在每个组后添加一行 NA:
ix <- unname(unlist(tapply(DFout$group, DFout$group, function(x) c(x, NA))))
ix[!is.na(ix)] <- seq_len(nrow(DFout))
DFout[ix, ]
2( data.table 转换为 data.table,设置键(对其进行排序(并使用rleid
分配组号。
library(data.table)
DT <- data.table(DF)
setkey(DT, Vendor, Buyer)
DT[, group := rleid(Vendor, Buyer)]
3( sqldf 另一种方法是使用 SQL。 这需要 github 上的 RSQLite 开发版本。 在这里,dense_rank
的作用类似于上面的rleid
。
library(sqldf)
sqldf("select *, dense_rank() over (order by Vendor, Buyer) as [group]
from DF
order by Vendor, Buyer")
给:
Vendor Buyer Amount group
1 A P 100 1
2 A P 290 1
3 B P 150 2
4 C Q 300 3
注意
DF <- structure(list(Vendor = structure(c(1L, 2L, 3L, 1L), .Label = c("A",
"B", "C"), class = "factor"), Buyer = structure(c(1L, 1L, 2L,
1L), .Label = c("P", "Q"), class = "factor"), Amount = c(100L,
150L, 300L, 290L)), class = "data.frame", row.names = c(NA, -4L
))