如何在保持其他列不变的同时将某些列的值放一行?

时间:2017-08-19 09:06:24

标签: r date

我有一个包含月度期限的数据框。它收集了几家公司的报告收入,这意味着价值每季度更新一次,而其他几个月只是" NA"。问题是一些公司在3月/ 6月/ 9月/ 12月报告,其他公司在4月/ 7月/ 10月/ 1月报告。

我的数据框如下所示:

datadate <-c(31012000,28022000,31032000,30042000,31052000,30062000,31072000,31082000,30092000,31102000,30112000,31122000,31012001)
AAPL <- c(NA,NA,100,NA,NA,120,NA,NA,110,NA,NA,135,NA)
MSFT <- c(NA,NA,55,NA,NA,70,NA,NA,65,NA,NA,60,NA)
GE <- c(NA,NA,NA,25,NA,NA,30,NA,NA,25,NA,NA,30)
PFE <- c(NA,NA,NA,20,NA,NA,15,NA,NA,25,NA,NA,30)
df <- data.frame (datadate,AAPL,MSFT,GE,PFE)
df$datadate <- strptime (df$datadate,format="%d%m%Y") 

但是,我希望所有值出现在3月/ 6月/ 9月/ 12月,如下所示:

GE.new <- c(NA,NA,25,NA,NA,30,NA,NA,25,NA,NA,30,NA)
PFE.new <- c(NA,NA,20,NA,NA,15,NA,NA,25,NA,NA,30,NA)
df.new <- data.frame (datadate,AAPL,MSFT,GE.new,PFE.new)

有谁知道怎么做?

3 个答案:

答案 0 :(得分:1)

以下是dplyr

的想法
library(dplyr)

df %>% 
 group_by(grp = cumsum(c(1, diff(rowSums(is.na(.[-1])) == 4) != 0))) %>% 
 mutate_at(vars(-datadate), funs(sum(., na.rm = TRUE))) %>% 
 mutate_at(vars(-datadate), funs(replace(., duplicated(.)|all(. == 0), NA))) %>% 
 ungroup() %>% 
 select(-grp)

给出,

# A tibble: 13 x 5
     datadate  AAPL  MSFT    GE   PFE
       <dttm> <dbl> <dbl> <dbl> <dbl>
 1 2000-01-31    NA    NA    NA    NA
 2 2000-02-28    NA    NA    NA    NA
 3 2000-03-31   100    55    25    20
 4 2000-04-30    NA    NA    NA    NA
 5 2000-05-31    NA    NA    NA    NA
 6 2000-06-30   120    70    30    15
 7 2000-07-31    NA    NA    NA    NA
 8 2000-08-31    NA    NA    NA    NA
 9 2000-09-30   110    65    25    25
10 2000-10-31    NA    NA    NA    NA
11 2000-11-30    NA    NA    NA    NA
12 2000-12-31   135    60    30    30
13 2001-01-31    NA    NA    NA    NA

答案 1 :(得分:0)

如果它总是与一个月后总是报告的公司相同,那么您可以选择将这些公司的价值提前一个月:

# preprocessing df as the POSIXlt format was throwing error for me
df$datadate <- as.POSIXct(df$datadate) 

df %>% mutate_at(vars(GE, PFE), lead, n = 1L)

     datadate AAPL MSFT GE PFE
1  2000-01-31   NA   NA NA  NA
2  2000-02-28   NA   NA NA  NA
3  2000-03-31  100   55 25  20
4  2000-04-30   NA   NA NA  NA
5  2000-05-31   NA   NA NA  NA
6  2000-06-30  120   70 30  15
7  2000-07-31   NA   NA NA  NA
8  2000-08-31   NA   NA NA  NA
9  2000-09-30  110   65 25  25
10 2000-10-31   NA   NA NA  NA
11 2000-11-30   NA   NA NA  NA
12 2000-12-31  135   60 30  30
13 2001-01-31   NA   NA NA  NA

答案 2 :(得分:0)

您的数据

我必须使用lubridate

更改日期
library(lubridate)
df$datadate <- dmy(df$datadate) 

替代dplyr解决方案

# Find companies that report in April
Apr <- df %>%
         mutate(month = month(datadate)) %>%
         group_by(month) %>%
         filter(month == 4) %>%
         ungroup(month) %>%
         select(-month)

companies <- colnames(Apr[2:ncol(Apr)])[!is.na(Apr[1,2:ncol(Apr)])]
# "GE"  "PFE"

通过过滤单个日期更容易完成,但因为您说公司可能在某一年停止存在,所以我先按月分组数据。我还假设一些公司可能会在1960年之后开始,这应该也应该考虑到这一点。

df1 <- df %>%
         mutate_at(vars(companies), funs(lead(.)))

输出

     datadate AAPL MSFT GE PFE
1  2000-01-31   NA   NA NA  NA
2  2000-02-28   NA   NA NA  NA 
3  2000-03-31  100   55 25  20
4  2000-04-30   NA   NA NA  NA
5  2000-05-31   NA   NA NA  NA
6  2000-06-30  120   70 30  15
7  2000-07-31   NA   NA NA  NA
8  2000-08-31   NA   NA NA  NA
9  2000-09-30  110   65 25  25
10 2000-10-31   NA   NA NA  NA
11 2000-11-30   NA   NA NA  NA
12 2000-12-31  135   60 30  30
13 2001-01-31   NA   NA NA  NA