2016-10-05 13 views
0

私はRを初めて使用しています。次のデータ(例)をcsvファイルとして保存しています。 0または1文字で月。私は1つの平均を保つ必要があります。複数の条件を使用して重複値を置き換えます。

Year Month Day Average 
2013 8  28 2.3 
2013 8  29 2.3 
2013 8  30 1.7 
2013 8  31 1.7 
2014 8  7 3 
2014 8  6 3 
2014 8  8 3 
2014 8  9 3 
2014 9  11 5.8 
2014 9  12 5.8 
2014 9  13 5.8 

私が期待した結果はまた、私はこのように置換された重複値を持つ行を削除できるようにしたいと思い、この

Year Month Day Average 
2013 8  28 2.3 
2013 8  29 0 
2013 8  30 1.7 
2013 8  31 0 
2014 8  7 3 
2014 8  6 0 
2014 8  8 0 
2014 8  9 0 
2014 9  11 5.8 
2014 9  12 0 
2014 9  13 0 

のようなものです:

Year Month Day Average 
2013 8  28 2.3 
2013 8  30 1.7 
2014 8  7 3 
2014 9  11 5.8 

私は2つのファイルを持っている必要があります.1つは重複値がゼロまたは文字に置き換えられ、もう1つは重複値のない平均値だけです。

ありがとうございます!

+0

'dput'などを使ってデータを共有することを検討してください。 – NGaffney

+1

2日連続で、データが異なる場合は意味がありますが、同じ数値になるように四捨五入すればドロップしますか?基礎となるデータはわかりませんが、潜在的に優れたデータを捨てるように聞こえます。プラス、注文は重要ですか?あなたは2014/8/6を除いてより早い平均を維持します。 – r2evans

答えて

0

data.frameの操作にdplyrを使用すると、日付 の操作では潤滑し、連続する繰り返し値を検索する場合はdiffとなります。

私は日付をソートして、サンプルのソリューションと正確には一致しないものを最も早く保存することに注意してください。

library(dplyr) 

## 
## Attaching package: 'dplyr' 

## The following objects are masked from 'package:stats': 
## 
##  filter, lag 

## The following objects are masked from 'package:base': 
## 
##  intersect, setdiff, setequal, union 

library(lubridate) 

## 
## Attaching package: 'lubridate' 

## The following object is masked from 'package:base': 
## 
##  date 

df1 <- read.table(
    text = " 
    Year Month Day Average 
    2013 8  28 2.3 
    2013 8  29 2.3 
    2013 8  30 1.7 
    2013 8  31 1.7 
    2014 8  7 3 
    2014 8  6 3 
    2014 8  8 3 
    2014 8  9 3 
    2014 9  11 5.8 
    2014 9  12 5.8 
    2014 9  13 5.8", 
header = T) 

df2 <- read.table(
    text = " 
    Year Month Day Average 
    2013 8  28 2.3 
    2013 8  29 0 
    2013 8  30 1.7 
    2013 8  31 0 
    2014 8  7 3 
    2014 8  6 0 
    2014 8  8 0 
    2014 8  9 0 
    2014 9  11 5.8 
    2014 9  12 0 
    2014 9  13 0", 
header = T) 

df3 <- read.table(
    text = " 
    Year Month Day Average 
    2013 8  28 2.3 
    2013 8  30 1.7 
    2014 8  7 3 
    2014 9  11 5.8", 
    header = T) 

df2 <- df1 %>% 
    mutate(date = ymd(paste(Year, Month, Day, sep = "-"))) %>% 
    arrange(date) %>% 
    mutate(is_consecutive_average = c(FALSE, diff(Average) == 0)) %>% 
    mutate(is_consecutive_day = c(FALSE, diff(date) == 1)) %>% 
    mutate(Average = Average * !(is_consecutive_average & is_consecutive_day)) %>% 
    select(-is_consecutive_average, -is_consecutive_day, -date) 

df2 

## Year Month Day Average 
## 1 2013  8 28  2.3 
## 2 2013  8 29  0.0 
## 3 2013  8 30  1.7 
## 4 2013  8 31  0.0 
## 5 2014  8 6  3.0 
## 6 2014  8 7  0.0 
## 7 2014  8 8  0.0 
## 8 2014  8 9  0.0 
## 9 2014  9 11  5.8 
## 10 2014  9 12  0.0 
## 11 2014  9 13  0.0 

df3 <- df2 %>% 
    filter(Average != 0) 

df3 

## Year Month Day Average 
## 1 2013  8 28  2.3 
## 2 2013  8 30  1.7 
## 3 2014  8 6  3.0 
## 4 2014  9 11  5.8 
+0

私の間違いは、今修正されました。 – NGaffney

0

ここdata.tableソリューションです:データ内

読む

data <- readr::read_csv(
    text, 
    col_names = TRUE, 
    trim_ws = TRUE 
) 

library(data.table) 
setDT(data) 

がよりよい形式に日付値に変換し、ソート

data[ , date := as.Date(paste0(Year, "-", Month, "-", Day)) ] 
setorder(data, date) 

前回のための新しい列を作成しますが、日付と平均値

data[ , prev.date := shift(date, 1L, type = "lag") ] 
data[ , prev.average := shift(Average, 1L, type = "lag") ] 

条件に基づいて、新しい「グループ」を作成するポイントをマークします。また、最初のレコードは新しいグループの先頭にしてください。

data[ , group := 0L 
     ][ as.integer(date - prev.date) > 1L | 
     Average != prev.average, group := 1L 
     ][ 1L, group := 1L ] 

「今、ユニークな番号

data[ , group := cumsum(group) ] 

としてグループをマークし、最大に集約して、あなたの第二の出力を得るゼロ

data[ group != 1L, Average := 0 ] 
first.output <- data[ , .(date, Average) ] 
head(first.output, 3) 

     date Average 
1: 2013-08-28  2.3 
2: 2013-08-29  0.0 
3: 2013-08-30  1.7 

で特定の値を置き換えることにより、平均をあなたの最初の所望の出力を取得します"値(0に等しくない唯一の値)、および最小"日付 "(グループの最初の値):

second.output <- data[ , .(date = min(date), 
          Average = max(Average)), 
         by = group ][ , .(date, Average) ] 

head(second.output, 3) 
     date Average 
1: 2013-08-28  2.3 
2: 2013-08-30  1.7 
3: 2014-08-06  3.0 

注:あなたはそう単純first.outputからゼロ「平均」値を持つ行を削除することによってsecond.outputを得ることができるが、それは「平均」は本当にゼロであるので、私はこの方法がより安全だと思う任意のグループを削除します。

関連する問題