Как объединить данные с одинаковыми именами строк в один столбец в R - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь переместить большой список с> 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?

Ответы [ 5 ]

0 голосов
/ 16 декабря 2018

A tidyverse решение с использованием данных @markus будет:

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
0 голосов
/ 16 декабря 2018

Вот несколько альтернатив.Они не используют никаких пакетов.

Предположим, что ввод 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)
0 голосов
/ 16 декабря 2018

Немного расширяя свои входные данные, вы можете использовать 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 do

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

data

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))
0 голосов
/ 16 декабря 2018

Это не точная копия Как преобразовать данные из длинного в широкий формат? , поэтому я отвечу.

Сначала создайте новый столбец 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                  
")
0 голосов
/ 16 декабря 2018

просто преобразовать его

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...