2017-06-27 14 views
0

私は、データフレーム内のデータを要約するための巧妙で速い方法を探しています。次のようにデータと所望の出力が見えます:カテゴリ変数の所与の値間のデータを要約する

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を合計し、Category Aの各2つの発生の間property最初と最後を維持する必要があります。ヘッドバンギング多くの後、私は、好ましくは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 

答えて

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 
2

ここではdata.tableとどうすればいいですか?まず「A」に囲まれた「B」の各スパンを識別するためのspanNumber変数を作成し、その後、あなたが指定した変数の計算:カテゴリベクトルのグループの実行にrleidを使用しています

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 
1

を代替data.table方法は

です
library(data.table) 
setDT(df)[, .(categoriesVector, 
       desiredData=sum(dataVector), 
       desiredProperty1=propertyVector[1], 
       desiredProperty2=propertyVector[.N]), 
      by=rleid(categoriesVector) 
      ][categoriesVector == "B",][, c("rleid", "categoriesVector") := NULL][] 

最初の[]の内容は、目的の出力を返し、カテゴリベクトルの実行に集計されます。 2番目のチェーンは、カテゴリベクトルがBであるものを維持することによって観測値をサブセット化します。3番目の[]は2つのヘルパー変数を削除し、最後の[]は結果を画面に出力するだけです。

これは

desiredData desiredProperty1 desiredProperty2 
1:   700    3    3 
2:  1200    5    7 
3:  1200    5    7 
4:  1200    5    7 
5:   100    9    9 
返します
関連する問題