汇总分类变量的给定值之间的数据

时间:2017-06-27 16:40:01

标签: r dplyr

我正在寻找一种巧妙而快速的方法来汇总数据框中的数据。数据和所需输出如下所示:

categoriesVector <- c("A", "A", "B", "A", "B", "B", "B", "A", "B")
propertyVector <- 1:length(categoriesVector)
dataVector <- 100 * rev(propertyVector)
df <- data.frame(categoriesVector, propertyVector, dataVector, stringsAsFactors = F)
df

desiredData <- c(700, sum(500, 400, 300), 100)
desiredProperty1 <- c(3, 5, 9)
desiredProperty2 <- c(3, 7, 9)
desiredDF <- data.frame(desiredData, desiredProperty1, desiredProperty2)
desiredDF

基本上我需要总结data并在property的每两次出现之间保留第一个和最后一个Category A。在经过大量的讨论之后,我发现了一个笨拙的解决方案,我希望在清晰度和性能方面找到改进,最好是dplyr

numRows <- dim(df)[1]
.groupedID <- rep(NA, numRows)
ID <- 1
.groupedID[[1]] <- ifelse(df$categoriesVector[[1]] == "A", 0, ID)
for(i in 2:numRows)
{
  if(df$categoriesVector[i] == "B")
  {
    .groupedID[i] <- ID
    if(df$categoriesVector[i - 1] == "B")
    {
      .groupedID[i] <- .groupedID[i - 1]
    }
    ID <- ID + 1
  } else
  {
    .groupedID[i] <- 0
  }
}

tempDF <- 
  df %>% 
  mutate(ID = .groupedID) %>% 
  filter(ID != 0) %>% 
  group_by(ID) %>% 
  summarise(desiredProperty1 = head(propertyVector, 1),
           desiredProperty2 = tail(propertyVector, 1),
           desiredData = sum(dataVector)) %>% 
  select(desiredData, desiredProperty1, desiredProperty2)
tempDF

3 个答案:

答案 0 :(得分:2)

您可以使用cumsum()进行分组,然后根据以下内容进行处理:

df %>% mutate(Agroups = cumsum(categoriesVector == "A")) %>%
    filter(categoriesVector == "B") %>%
    group_by(Agroups) %>%
    summarise(propertyStart = min(propertyVector),
              propertyEnd = max(propertyVector),
              dataTotal = sum(dataVector))

# A tibble: 3 x 4
  Agroups propertyStart propertyEnd dataTotal
    <int>         <dbl>       <dbl>     <dbl>
1       2             3           3       700
2       3             5           7      1200
3       4             9           9       100

答案 1 :(得分:2)

以下是我对data.table的处理方法。首先创建spanNumber变量以标识“A”包围的每个“B”跨度,然后计算您指定的变量:

library(data.table)
setDT(df)
df[, catShiftConcat := paste0(categoriesVector, shift(categoriesVector, fill = "A"))]
df[categoriesVector == "B", spanNumber := cumsum(catShiftConcat == "BA")]
df[!is.na(spanNumber) , .(desiredData = sum(dataVector), 
     desiredProperty1 = propertyVector[1], 
     desiredProperty2 = propertyVector[.N]), by = spanNumber]
##    spanNumber desiredData desiredProperty1 desiredProperty2
## 1:          1         700                3                3
## 2:          2        1200                5                7
## 3:          3         100                9                9

答案 2 :(得分:1)

使用/** * @param {!Object} obj * @return {boolean} */ function isFruit(obj) { return obj.color && obj.name; } 对类别向量的分组进行分组的替代data.table方法是

rleid

第一个library(data.table) setDT(df)[, .(categoriesVector, desiredData=sum(dataVector), desiredProperty1=propertyVector[1], desiredProperty2=propertyVector[.N]), by=rleid(categoriesVector) ][categoriesVector == "B",][, c("rleid", "categoriesVector") := NULL][] 中的内容返回所需的输出,并计算汇总到类别向量的运行。第二个链通过保留类别向量为B的那些来对观察值进行子集化。第三个[]删除两个辅助变量,最后[]就是将结果打印到屏幕上。

返回

[]