R - 从长到宽再回到相同的长格式
R - From long to wide and back to the same long format
我有长格式的 Compustat 数据,我通过 spread
(来自 tidyr
包)将其转换为宽格式。
然后我做了一些计算,之后我想再次将数据帧恢复为长格式。是否有任何类型的 "memory" 函数,以便我的新长数据帧与旧数据帧完全相同(相同顺序)。
问题是有很多NA
,每只股票的数据都是从股票首次上市开始到退市后或样本结束时结束。我的样本从 1960 年到 2015 年(每季度)。当然,并非所有股票都有所有日期的数据,但当我从宽格式返回到长格式时,每只股票都会获得从 1960.1 到 2015.4 的所有日期。这个长格式数据帧是我正在构建的乐谱的一部分,我必须将它与其他长格式数据帧进行比较(它们都具有相同的 kypermno 和日期顺序),因此我需要将宽数据帧转换回与新值完全相同的原始形式。
编辑:这是我的问题的一个例子:
长格式'original'(称为'test'):
`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 都被省略了(不仅是新创建的 NA ).
因此,当我再次从宽格式返回到长格式时,我想获得旧的(18 行长)长格式数据帧,而不是我得到的数据帧(有 24 行和 "new" NA)。
我希望我的问题现在可以理解了。
PS:如您所见,我没有设法在第一列中获得 kypermno,在第二列中获得 fyyyyq(在返回到长格式之后),但我认为这不会影响以上问题。
有一个 fill=
选项允许您选择要用于 "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)
但也许你应该问问自己是否真的有必要将你的数据转换成宽格式...
我有长格式的 Compustat 数据,我通过 spread
(来自 tidyr
包)将其转换为宽格式。
然后我做了一些计算,之后我想再次将数据帧恢复为长格式。是否有任何类型的 "memory" 函数,以便我的新长数据帧与旧数据帧完全相同(相同顺序)。
问题是有很多NA
,每只股票的数据都是从股票首次上市开始到退市后或样本结束时结束。我的样本从 1960 年到 2015 年(每季度)。当然,并非所有股票都有所有日期的数据,但当我从宽格式返回到长格式时,每只股票都会获得从 1960.1 到 2015.4 的所有日期。这个长格式数据帧是我正在构建的乐谱的一部分,我必须将它与其他长格式数据帧进行比较(它们都具有相同的 kypermno 和日期顺序),因此我需要将宽数据帧转换回与新值完全相同的原始形式。
编辑:这是我的问题的一个例子:
长格式'original'(称为'test'):
`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 都被省略了(不仅是新创建的 NA ). 因此,当我再次从宽格式返回到长格式时,我想获得旧的(18 行长)长格式数据帧,而不是我得到的数据帧(有 24 行和 "new" NA)。
我希望我的问题现在可以理解了。
PS:如您所见,我没有设法在第一列中获得 kypermno,在第二列中获得 fyyyyq(在返回到长格式之后),但我认为这不会影响以上问题。
有一个 fill=
选项允许您选择要用于 "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)
但也许你应该问问自己是否真的有必要将你的数据转换成宽格式...