我想转动数据框
我的输入数据为
第一个输入
MSFT AAPL GOOG
10 20 40
第一次输出
Id Symbol Value
T1 MSFT 10
T1 AAPL 20
T1 GOOG 40
--------------------------------------
--------------------------------------
2nd Input
AAPL GOOG
30 60
第二次输出
Id Symbol Value
T2 AAPL 30
T2 GOOG 60
----------------------------------------------- ----------------------
{for循环中生成Input1
和Input2
。一行R
代码可以解决这两个问题,以便最终输出如下。
Id Symbol Value
T1 MSFT 10
T1 AAPL 20
T1 GOOG 40
T2 AAPL 30
T2 GOOG 60
效果必须。我在Stackoverflow上的其他问题上看到rbind
或list
提供的性能低于预分配空间。
答案 0 :(得分:4)
这是用dplyr和tidyr做的一种方法(由konvas评论):
library(dplyr)
library(tidyr)
df1 <- gather(df1, Symbol, Value, MSFT:GOOG) %>% mutate(Id = "T1")
df2 <- gather(df2, Symbol, Value, AAPL:GOOG) %>% mutate(Id = "T2")
dfs <- rbind_list(df1, df2)
同样可以写在问题所要求的“单行R代码”中:
rbind_list(gather(df1, Symbol, Value, MSFT:GOOG) %>% mutate(Id = "T1"),
gather(df2, Symbol, Value, AAPL:GOOG) %>% mutate(Id = "T2"))
或使用reshape2
和基础R的rbind
:
library(reshape2)
rbind(transform(melt(df1), Id = "T1"), transform(melt(df2), Id = "T2"))
答案 1 :(得分:4)
语法 - 这是简洁的:
reshape2::melt(list(T1=Input1, T2=Input2))
# variable value L1
# 1 MSFT 10 T1
# 2 AAPL 20 T1
# 3 GOOG 40 T1
# 4 AAPL 30 T2
# 5 GOOG 60 T2
然而,它在内部使用rbind.fill
doesn't scale well(尽管是旧的基准)。在搜索rind.fill
缓慢时,我遇到了另一个interesting link/post。
答案 2 :(得分:3)
假设您的原始数据是:
> df1
MSFT AAPL GOOG
1 10 20 40
没有dplyr和plyr但重塑形式包(用于重命名):
toggle <- function(df, id){
rename(transform(t(df), id=id, Symbol=rownames(t(df)), c("X_data"="Value"))
}
rbindlist(list(toggle(df1,'T1'), toggle(df2,'T2')))
答案 3 :(得分:1)
另一种选择是使用unnest/gather/filter
tidyr/dplyr
组合
library(dplyr)
library(tidyr)
unnest(setNames(list(Input1, Input2), paste0("T",1:2)),'Id') %>%
gather(Symbol, Value, -Id) %>%
filter(!is.na(Value))
# Id Symbol Value
#1 T1 MSFT 10
#2 T1 AAPL 20
#3 T2 AAPL 30
#4 T1 GOOG 40
#5 T2 GOOG 60
Input1 <- structure(list(MSFT = 10L, AAPL = 20L, GOOG = 40L), .Names =
c("MSFT", "AAPL", "GOOG"), class = "data.frame", row.names = c(NA, -1L))
Input2 <- structure(list(AAPL = 30L, GOOG = 60L), .Names = c("AAPL", "GOOG"
), class = "data.frame", row.names = c(NA, -1L))