在r中旋转数据框并添加具有自定义值的列

时间:2014-12-22 14:12:31

标签: r dataframe pivot

我想转动数据框
我的输入数据为

第一个输入

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循环中生成Input1Input2。一行R代码可以解决这两个问题,以便最终输出如下。

Id  Symbol  Value
T1  MSFT    10
T1  AAPL    20
T1  GOOG    40
T2  AAPL    30
T2  GOOG    60

效果必须。我在Stackoverflow上的其他问题上看到rbindlist提供的性能低于预分配空间。

4 个答案:

答案 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))