R - 从长到宽,再回到相同的长格式

时间:2017-05-07 00:47:56

标签: r dataframe reshape tidyr

我有长格式的Compustat数据,我通过spread(来自tidyr包)转换为宽格式。

然后我做了一些计算,然后我想再次将数据帧恢复为长格式。是否存在任何类型的“记忆”功能,因此我的新长数据帧与旧数据帧的方式完全相同(相同的顺序)。

问题是有很多NA个,每个股票的数据在股票首次上市时开始,在退市后或在样本结束时结束。我的样本从1960年到2015年(季刊)。当然并非所有股票都有所有日期的数据,但是当我从宽幅格式回到长格式时,每只股票都会从1960.1到2015.4获得所有日期。这个长格式数据框是我正在构建的分数的一部分,我必须将它与其他长格式数据帧进行比较(所有这些数据帧都由kypermno和date具有相同的顺序),因为我需要将宽数据帧转换回确切的原始形式与新值。

编辑:这是我的问题的一个例子:

长格式'原创'(称为'测试'):

    `kypermno fyyyyq ROE_Q
      <int>  <int> <dbl>
1      1001   1985  0.56
2      1001   1986  0.43
3      1001   1987  0.78
4      1001   1988    NA
5      1001   1989  0.34
6      1001   1990  0.76
7      1002   1980  0.12
8      1002   1981  0.67
9      1002   1982  0.12
10     1002   1983  0.56
11     1002   1984    NA
12     1002   1985  0.91
13     1002   1986  0.45
14     1002   1987  0.23
15     1002   1988  0.54
16     1002   1989  0.14
17     1002   1990  0.19
18     1002   1991  0.27`

使用以下代码我将其放在宽格式中:

dat_wide <- spread(test, kypermno, ROE_Q)

现在采用宽屏格式,如下所示:

 fyyyyq `1001` `1002`
*   <int>  <dbl>  <dbl>
1    1980     NA   0.12
2    1981     NA   0.67
3    1982     NA   0.12
4    1983     NA   0.56
5    1984     NA     NA
6    1985   0.56   0.91
7    1986   0.43   0.45
8    1987   0.78   0.23
9    1988     NA   0.54
10   1989   0.34   0.14
11   1990   0.76   0.19
12   1991     NA   0.27

当我以长格式把它放回去时,它变成了这个:

dat_long <- gather(dat_wide, key = 'fyyyyq', value = 'ROE_Q', -kypermno)

fyyyyq kypermno ROE_Q
    <int>    <chr> <dbl>
1    1980     1001    NA
2    1981     1001    NA
3    1982     1001    NA
4    1983     1001    NA
5    1984     1001    NA
6    1985     1001  0.56
7    1986     1001  0.43
8    1987     1001  0.78
9    1988     1001    NA
10   1989     1001  0.34
11   1990     1001  0.76
12   1991     1001    NA
13   1980     1002  0.12
14   1981     1002  0.67
15   1982     1002  0.12
16   1983     1002  0.56
17   1984     1002    NA
18   1985     1002  0.91
19   1986     1002  0.45
20   1987     1002  0.23
21   1988     1002  0.54
22   1989     1002  0.14
23   1990     1002  0.19
24   1991     1002  0.27

正如您所看到的,现在有更多的NA(因为它们是从长到宽创建的)并且NA省略不是一个选项,因为所有NA都被省略(不仅是新创建的)。 所以当我再次从宽格式再到长格式时,我想得到旧的(18行长)格式数据帧,而不是我得到的数据帧(有24行和“新”NAs)。

我希望我的问题现在可以理解了。

PS:正如你所看到的,我没有设法在第一列获得kypermno而在第二列获得fyyyyq(在回到长格式之后),但我认为它不会影响上面的问题。

1 个答案:

答案 0 :(得分:1)

有一个fill=选项,允许您选择用于“填补”空白的值。可悲的是,它也取代了原来的NA,所以没用。

使用原始测试数据来消除原本不存在的案例是一种不优雅的解决方案。

注意:我必须略微修改你的代码才能使其正常工作。

test <- read.table(text = 
'ID kypermno fyyyyq ROE_Q
1      1001   1985  0.56
2      1001   1986  0.43
3      1001   1987  0.78
4      1001   1988    NA
5      1001   1989  0.34
6      1001   1990  0.76
7      1002   1980  0.12
8      1002   1981  0.67
9      1002   1982  0.12
10     1002   1983  0.56
11     1002   1984    NA
12     1002   1985  0.91
13     1002   1986  0.45
14     1002   1987  0.23
15     1002   1988  0.54
16     1002   1989  0.14
17     1002   1990  0.19
18     1002   1991  0.27',
header = TRUE)
test <- test[,-1]

library(tidyr)
dat_wide <- spread(test, kypermno, ROE_Q)
dat_wide

dat_long <- gather(dat_wide, key = 'kypermno', value = ROE_Q, -fyyyyq)
dat_long


# Keep only the original data
dat_long[ paste(dat_long[,2], dat_long[,1]) %in% paste(test[,1], test[,2]),]

# Alternative (shorter and probably better)
merge(test[,1:2], dat_long, all.x=TRUE)

但也许您应该问自己是否真的有必要以宽幅格式转换数据......