使用r

时间:2016-10-05 03:22:29

标签: r

我是R的新手,我有以下数据(示例)作为csv文件,如果它们在相似的年份和月份中连续几天发生,则我想替换任何重复值,或者是零或一个字母。我只需要保持一个平均值。

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 个答案:

答案 0 :(得分:0)

使用dplyr进行data.frame操作,使用rubridate进行日期 操纵和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

答案 1 :(得分: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" ) ]

标记一个新的&#34;组&#34;应根据您的标准创建。同时将第一条记录标记为新组的开头,因为我们可以认为它是。

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

通过用零替换特定值来获取您想要的第一个输出

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

现在将组标记为唯一编号

data[ , group := cumsum( group ) ]

通过汇总到最大值&#34;平均值&#34;来获得第二个输出。值(将是唯一不等于零的值),以及最小值&#34; date&#34; value(该组中的第一个):

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

注意:您可能只需删除零&#34;平均值&#34;的行就可以获得second.output。来自first.output的值,但它会删除&#34; Average&#34;真的是零,所以我认为这种方法更安全。