【问题标题】:Grouping data based on repetitive records using R使用 R 根据重复记录对数据进行分组
【发布时间】:2019-07-10 21:44:26
【问题描述】:

我有一个包含重复记录/常见记录的数据集。它看起来像这样:

| 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 |

【问题讨论】:

  • 看来你需要orderarrange library(dplyr); df1 %>% arrange(Vendor, Buyer)
  • @akrun 是的,我使用了安排,但您能帮我解决问题的编辑部分吗?

标签: r split grouping multiple-records


【解决方案1】:

在下文中,我们对数据框进行排序并添加一个组列,以便对各个组进行后续处理。例如,要在不创建 DF 的大拆分的情况下处理组:

for(g in unique(DFout$group)) {
  DFsub <- subset(DFout, group == g)
  ... process DFsub ...
}

1) Base 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,设置key(排序)并使用rleid分配组号。

library(data.table)

DT <- data.table(DF)
setkey(DT, Vendor, Buyer)
DT[, group := rleid(Vendor, Buyer)]

3) sqldf 另一种方法是使用 SQL。这需要RSQLite on github的开发版本。这里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
))

【讨论】:

  • 第一种方法帮助我找到了答案。在目前的情况下,如果我想消除所有买家以及具有单一交易的供应商,在这种情况下供应商 = c 和买家 = Q。另外,让我们假设我们在问题集中也有一个日期字段。那么,一旦我们将买家和供应商分组在一起,我们应该如何按升序对它们进行排序?
  • subset(DFout, ave(group, group, FUN = length) &gt; 1) 将删除只有一行的组。答案已经显示了如何进行排序。
  • 我在原始数据中尝试了第一种方法,它似乎不起作用。每个买家都会有多个供应商。所以,我首先想将相似的买家分组在一起,然后为每个买家分组相似的供应商,然后分别为每个组按升序对交易进行排序。
  • 如果您想以这种方式更改问题,请按买方和供应商排序,而不是按供应商和买方排序。
猜你喜欢
  • 2014-09-03
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 2015-05-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
相关资源
最近更新 更多