我正在尝试从中移动一个带有> 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循环将其循环的更充分的方法?
答案 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