将数据重塑为面板形式
Reshaping Data into panel form
我有数据,其中对象名称是一个变量名称,如 EPS
、Profit
等(大约 25 个这样的不同对象)
数据是这样排列的:
EPS <- read.table(text = "
Year Microsoft Facebook
2001 12 20
2002 15 23
2003 16 19
", header = TRUE)
Profit <- read.table(text = "
Year Microsoft Facebook
2001 15 36
2002 19 40
2003 25 45
", header = TRUE)
我想要这样的输出:
Year Co_Name EPS Profit
2001 Microsoft 12 15
2002 Microsoft 15 19
2003 Microsoft 16 25
2001 Facebook 20 36
2002 Facebook 23 40
2003 Facebook 19 45
如何实现?有没有办法将所有变量的数据安排为一个对象?每个变量的数据都从 EPS.csv、Profit.csv 等 csv 文件导入到 R 中。有没有什么方法可以创建从导入到以所需格式排列数据的循环?
我们可以在list
中获取数据集。如果我们已经创建了 'EPS'、'Profit' 作为对象,使用 mget
获取 list
中的对象,使用 rbindlist
转换为单个 data.table , melt
到 long
格式并用 dcast
.
重塑回 'wide'
library(data.table)#v1.9.6+
DT <- rbindlist(mget(c('EPS', 'Profit')), idcol=TRUE)
DT1 <- dcast(melt(rbindlist(mget(c('EPS', 'Profit')), idcol=TRUE),
id.var=c('.id', 'Year'), variable.name='Co_Name'),
Year+Co_Name~.id, value.var='value')
DT1
# Year Co_Name EPS Profit
#1: 2001 Microsoft 12 15
#2: 2001 Facebook 20 36
#3: 2002 Microsoft 15 19
#4: 2002 Facebook 23 40
#5: 2003 Microsoft 16 25
#6: 2003 Facebook 19 45
如果我们需要安排,使用order
DT1[order(factor(Co_Name, levels=unique(Co_Name)))]
为了好玩,我们也可以使用 dplyr
、tidyr
和 purrr
获得相同的结果。
library(dplyr)
library(tidyr)
library(readr)
library(purrr)
list_of_csv <- list.files(path = ".", pattern = ".csv", full.names = TRUE)
file_name <- gsub(".csv", "", basename(list_of_csv))
list_of_csv %>%
map(~ read_csv(.)) %>%
map(~ gather(data = ., key = co_name, value = value, -year)) %>%
reduce(inner_join, by = c("year", "co_name")) %>%
setNames(., c("year", "co_name", file_name))
## Source: local data frame [6 x 4]
## year co_name eps profit
## (int) (fctr) (int) (int)
## 1 2001 microsoft 12 15
## 2 2002 microsoft 15 19
## 3 2003 microsoft 16 25
## 4 2001 facebook 20 36
## 5 2002 facebook 23 40
## 6 2003 facebook 19 45
我有数据,其中对象名称是一个变量名称,如 EPS
、Profit
等(大约 25 个这样的不同对象)
数据是这样排列的:
EPS <- read.table(text = "
Year Microsoft Facebook
2001 12 20
2002 15 23
2003 16 19
", header = TRUE)
Profit <- read.table(text = "
Year Microsoft Facebook
2001 15 36
2002 19 40
2003 25 45
", header = TRUE)
我想要这样的输出:
Year Co_Name EPS Profit
2001 Microsoft 12 15
2002 Microsoft 15 19
2003 Microsoft 16 25
2001 Facebook 20 36
2002 Facebook 23 40
2003 Facebook 19 45
如何实现?有没有办法将所有变量的数据安排为一个对象?每个变量的数据都从 EPS.csv、Profit.csv 等 csv 文件导入到 R 中。有没有什么方法可以创建从导入到以所需格式排列数据的循环?
我们可以在list
中获取数据集。如果我们已经创建了 'EPS'、'Profit' 作为对象,使用 mget
获取 list
中的对象,使用 rbindlist
转换为单个 data.table , melt
到 long
格式并用 dcast
.
library(data.table)#v1.9.6+
DT <- rbindlist(mget(c('EPS', 'Profit')), idcol=TRUE)
DT1 <- dcast(melt(rbindlist(mget(c('EPS', 'Profit')), idcol=TRUE),
id.var=c('.id', 'Year'), variable.name='Co_Name'),
Year+Co_Name~.id, value.var='value')
DT1
# Year Co_Name EPS Profit
#1: 2001 Microsoft 12 15
#2: 2001 Facebook 20 36
#3: 2002 Microsoft 15 19
#4: 2002 Facebook 23 40
#5: 2003 Microsoft 16 25
#6: 2003 Facebook 19 45
如果我们需要安排,使用order
DT1[order(factor(Co_Name, levels=unique(Co_Name)))]
为了好玩,我们也可以使用 dplyr
、tidyr
和 purrr
获得相同的结果。
library(dplyr)
library(tidyr)
library(readr)
library(purrr)
list_of_csv <- list.files(path = ".", pattern = ".csv", full.names = TRUE)
file_name <- gsub(".csv", "", basename(list_of_csv))
list_of_csv %>%
map(~ read_csv(.)) %>%
map(~ gather(data = ., key = co_name, value = value, -year)) %>%
reduce(inner_join, by = c("year", "co_name")) %>%
setNames(., c("year", "co_name", file_name))
## Source: local data frame [6 x 4]
## year co_name eps profit
## (int) (fctr) (int) (int)
## 1 2001 microsoft 12 15
## 2 2002 microsoft 15 19
## 3 2003 microsoft 16 25
## 4 2001 facebook 20 36
## 5 2002 facebook 23 40
## 6 2003 facebook 19 45