如何将具有相同行名的数据合并到R中的一列

时间:2018-12-16 11:50:36

标签: r

我正在尝试从中移动一个带有> 200000个字符的大列表:

startTime  1
max        3
min        1        
EndTime    2
avg        2     
startTime  2
max       ..
min       ..
EndTime   ..
avg       ..
..

到这样的数据框:

startTime  max  min  EndTime  avg  
1          3    1    2        2
2          ..   ..   ..       ..

我通过for循环来管理它。这需要很多时间。还有没有通过for循环将其循环的更充分的方法?

5 个答案:

答案 0 :(得分:1)

稍微扩展输入数据,就可以使用unstack中的base R

输入:

dat
#          V1 V2
#1  startTime  1
#2        max  3
#3        min  1
#4    EndTime  2
#5        avg  2
#6  startTime  2
#7        max  3
#8        min  4
#9    EndTime  5
#10       avg  6

结果:

out <- unstack(dat, V2 ~ V1)
out
#  avg EndTime max min startTime
#1   2       2   3   1         1
#2   6       5   3   4         2

如果您希望列名的顺序与dat$V1中出现的列的顺序相同

out <- out[unique(dat$V1)]

数据

dat <- structure(list(V1 = c("startTime", "max", "min", "EndTime", "avg", 
"startTime", "max", "min", "EndTime", "avg"), V2 = c(1L, 3L, 
1L, 2L, 2L, 2L, 3L, 4L, 5L, 6L)), .Names = c("V1", "V2"), class = "data.frame", row.names = c(NA, 
-10L))

答案 1 :(得分:0)

只需转换

library( data.table )

dt <- data.table::fread(" startTime  1
max        3
                        min        1        
                        EndTime    2
                        avg        2     
                        startTime  2", header = FALSE)

as.data.table( t( dt ) )

#           V1  V2  V3      V4  V5        V6
# 1: startTime max min EndTime avg startTime
# 2:         1   3   1       2   2         2

答案 2 :(得分:0)

这与How to reshape data from long to wide format?并不完全相同,所以我会回答。

首先创建一个新列ID,然后使用重复项中的一种解决方案。我将使用基于软件包reshape2的解决方案。

pattern <- as.character(df1[1, 1])
ipat <- grep(pattern, df1[[1]])

df1$ID <- rep(seq_along(ipat), nrow(df1)/length(ipat))

library(reshape2)

result <- dcast(df1, ID ~ V1, value.var = "V2")[-1]
#  avg EndTime max min startTime
#1   2       3   4   1         1
#2   1       2   3   2         2

最终清理,将输入数据集df1恢复原样。

df1 <- df1[-ncol(df1)]

数据。

df1 <- read.table(text = "
startTime  1
max        3
min        1        
EndTime    2
avg        2     
startTime  2
max        4
min        2
EndTime    3
avg        1                  
")

答案 3 :(得分:0)

这里有一些替代方法。他们不使用任何软件包。

假设输入DF在末尾的注释中可重复显示。

1)xtabs 代码的第一行将第一列转换为字符,以防万一。注释中显示的数据不需要我们使用它,但它不会受到损害,如果该列是要考虑的因素以使其处于已知状态,则可能会很有用。

然后将V1列转换为水平顺序按顺序出现的因数,这样它们就不会在输出时重新排列。还要定义更好的名称,并创建一个“组号”向量,该向量将5行的第一组编号为1,将第二组2编号,依此类推。

最后使用xtabs创建所需的表。如果您更喜欢数据框作为输出而不是表,请使用as.data.frame(xt)

DF2 <- transform(DF, V1 = as.character(V1))
DF2 <- transform(DF2, Stat = factor(V1, levels = V1[1:5]), 
  Value = V2,
  Group = cumsum(V1== "startTime"))
xt <- xtabs(Value ~ Group + Stat, DF2)
xt

给予:

     Stat
Group startTime max min EndTime avg
    1         1   3   1       2   2
    2         2   4   1       3   2

2)矩阵(更短)。它给出一个矩阵。如果需要数据框,请使用as.data.frame(m)

m <- matrix(DF$V2,, 5, byrow = TRUE, list(NULL, DF$V1[1:5]))
m

给予:

     startTime max min EndTime avg
[1,]         1   3   1       2   2
[2,]         2   4   1       3   2

注意

可复制形式的输入。我添加了几行。

Lines <- "
startTime  1
max        3
min        1        
EndTime    2
avg        2     
startTime  2
max        4
min        1
EndTime    3
avg        2"
DF <- read.table(text = Lines, as.is = TRUE)

答案 4 :(得分:0)

使用@markus数据的tidyverse解决方案是:

library(tidyverse)
dat %>% 
  group_by(tmp = cumsum(V1=="startTime"))  %>%
  spread(V1,V2) %>%
  ungroup %>%
  select(-tmp)

# # A tibble: 2 x 5
#     avg EndTime   max   min startTime
#   <int>   <int> <int> <int>     <int>
# 1     2       2     3     1         1
# 2     6       5     3     4         2