вырезать столбцы и связывать их с датафреймом в r - PullRequest
2 голосов
/ 06 июня 2019

В моих данных есть несколько повторяющихся столбцов, и я хочу вырезать дубликаты столбцов и повторно связать их.

Я сделал это в своем коде, но мне интересно, есть ли более эффективный способ сделать это.

df <- data.frame(a = 1:4,
             b = 5:8,
             a.1 = letters[1:4],
             b.1 = letters[5:8],
             a.2 = LETTERS[1:4],
             b.2 = LETTERS[5:8])
names(df)[c(1,3,5)] <- "a"
names(df)[c(2,4,6)] <- 'b'

d1 <- df[,1:2]
d2 <- df[,3:4]
d3 <- df[,5:6]
d <- rbind(d1,d2) %>% rbind(d3)

Ответы [ 2 ]

2 голосов
/ 06 июня 2019

Другая базовая опция R - это использование split.default и разделение фрейма данных на основе names столбца, unlist их и cbind отдельных списков.

do.call(cbind.data.frame, lapply(split.default(df, names(df)), unlist))

#     a b
#a1   1 5
#a2   2 6
#a3   3 7
#a4   4 8
#a.11 a e
#a.12 b f
#a.13 c g
#a.14 d h
#a.21 A E
#a.22 B F
#a.23 C G
#a.24 D H

Вы можете установить имена строкдо NULL, если это не нужно.Также чтение символов как символов, а не факторов, установив stringsAsFactors = FALSE.

1 голос
/ 06 июня 2019

1) Опция - это циклическая перебивка unique names набора данных, подмножество столбцов набора данных на основе этого, unlist и присвоение именам строк NULL

out <- as.data.frame(sapply(unique(names(df)), 
        function(x) unlist(df[names(df) ==x])))
row.names(out) <- NULL
out
#   a b
#1  1 5
#2  2 6
#3  3 7
#4  4 8
#5  a e
#6  b f
#7  c g
#8  d h
#9  A E
#10 B F
#11 C G
#12 D H

2) Или можно создать data.frame, выбрав альтернативные столбцы

data.frame(a = unlist(df[c(TRUE, FALSE)]), b = unlist(df[c(FALSE, TRUE)]))

3) Или unlist данных, создайте логическое условие на основе имен, а затем задайте вектор для создания data.frame

v1 <- unlist(df)
i1 <- grepl("a", names(v1))
data.frame(a = v1[i1], b = v1[!i1])

4a) Или с помощьюsplit.default

do.call(rbind, split.default(df, cumsum(names(df) == "a")))

4b) Использование %%

do.call(rbind, split.default(df, cumsum(seq_along(df) %% 2)))

5) Использование seq и lapply

do.call(rbind, lapply(seq(1, ncol(df), by = 2), function(i) df[i:(i+1)]))

6) Или с split.default и bind_rows

library(dplyr)
bind_rows(split.default(df, cumsum(names(df) == "a")))

7) Или сsplit.default и rbindlist

library(data.table)
rbindlist(split.default(df, cumsum(names(df) == "a")))

8) Или другой вариант melt из data.table

library(data.table)
melt(setDT(df), measure = patterns("a", "b"), 
   value.name = c("a", "b"))[, variable := NULL][]

ПРИМЕЧАНИЕ.убедитесь, что наборы данных созданы с stringsAsFactors = FALSE

data

df <- data.frame(a = 1:4,
             b = 5:8,
             a.1 = letters[1:4],
             b.1 = letters[5:8],
             a.2 = LETTERS[1:4],
             b.2 = LETTERS[5:8], stringsAsFactors = FALSE)
names(df)[c(1,3,5)] <- "a"
names(df)[c(2,4,6)] <- 'b'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...