как мне выполнить поиск столбцов с одинаковыми именами, добавить значения столбцов и заменить эти столбцы с одинаковыми именами на их сумму? Используя R

#r

#r

Вопрос:

У меня есть фрейм данных, в котором несколько последовательных столбцов имеют одинаковое имя. Мне нужно выполнить поиск этих столбцов, добавить их значения для каждой строки, удалить один столбец и заменить другой их суммой. предварительно не зная, какие шаблоны дублируются, возможно, придется сравнить имя одного столбца со следующим, чтобы увидеть, есть ли совпадение.

Кто-нибудь может помочь?

Заранее спасибо.

Ответ №1:

 > dfrm <- data.frame(a = 1:10, b= 1:10, cc= 1:10, dd=1:10, ee=1:10)
> names(dfrm) <- c("a", "a", "b", "b", "b")
> sapply(unique(names(dfrm)[duplicated(names(dfrm))]), 
      function(x) Reduce(" ", dfrm[ , grep(x, names(dfrm))]) )
       a  b
 [1,]  2  3
 [2,]  4  6
 [3,]  6  9
 [4,]  8 12
 [5,] 10 15
 [6,] 12 18
 [7,] 14 21
 [8,] 16 24
 [9,] 18 27
[10,] 20 30
  

РЕДАКТИРОВАНИЕ 2: Использование rowSums позволяет упростить первый аргумент sapply только unique(names(dfrm)) за счет необходимости не забывать включать drop=FALSE в «[«:

 sapply(unique(names(dfrm)), 
       function(x) rowSums( dfrm[ , grep(x, names(dfrm)), drop=FALSE]) )
  

Чтобы разобраться с NA:

 sapply(unique(names(dfrm)), 
      function(x) apply(dfrm[grep(x, names(dfrm))], 1, 
              function(y) if ( all(is.na(y)) ) {NA} else { sum(y, na.rm=TRUE) }
       )               )
  

(Примечание для редактирования: обратился к контрпримеру Tommy, поместив unique вокруг конструкции names(.)[.].
Ошибочный код был:

 sapply(names(dfrm)[unique(duplicated(names(dfrm)))], 
     function(x) Reduce(" ", dfrm[ , grep(x, names(dfrm))]) )
  

Комментарии:

1. Не работает на dfrm=data.frame(a=1:10, b=20:29, a=101:110, b=200:209, a=1001:1010, check.names=F)

2. @Tommy. Спасибо. Указывает, что я должен был обернуть уникальность вокруг имен (dfrm) [дублируется ….] Исправлено.

3. Спасибо, хотя я подозреваю, что rowSums было бы быстрее.

4. В моих данных отсутствуют значения. Как я могу изменить эту функцию, чтобы она выдавала мне: 1) NA, если отсутствуют все значения столбцов в группе переменных, и 2) значение, если есть хотя бы одно значение. Я попытался использовать условные обозначения и проверить, использует ли NA is.na () но не удалось. Не удается использовать na.rm=FALSE или TRUE.

Ответ №2:

Вот мой один лайнер

 # transpose data frame, sum by group = rowname, transpose back.
t(rowsum(t(dfrm), group = rownames(t(dfrm))))
  

Комментарии:

1. 1. Очень аккуратно, хотя стоит отметить, что, как написано, это потребуется as.data.frame() , если это то, что требуется.

2. @Henry. ДА. Было бы легко преобразовать этот вывод в любой формат, который захочет OP. Поскольку он использует rowsum который вызывает функцию C, он быстр и выполняется в 1,5 раза быстрее в примере dataset. Я подозреваю, что это было бы еще быстрее в большем фрейме данных.

Ответ №3:

Один из способов — идентифицировать дубликаты, используя (неожиданно) duplicated функцию, а затем перебирать их для вычисления сумм. Вот пример:

 dat.dup <- data.frame(x=1:10, x=1:10, x=1:10, y=1:10, y=1:10, z=1:10, check.names=FALSE)
dups <- unique(names(dat.dup)[duplicated(names(dat.dup))])
for (i in dups) {
dat.dup[[i]] <- rowSums(dat.dup[names(dat.dup) == i])
}
dat <- dat.dup[!duplicated(names(dat.dup))]
  

Комментарии:

1. спасибо, это была моя оригинальная идея, но я не смог ее закодировать. И я также не был ознакомлен с «уникальным».

Ответ №4:

Некоторые примеры данных.

 dfr <- data.frame(
  foo = rnorm(20),
  bar = 1:20,
  bar = runif(20),
  check.names = FALSE
)
  

Метод: Перебор уникальных имен столбцов; если существует только один столбец с таким именем, то выбор всех столбцов с этим nme вернет вектор, но если есть дубликаты, это также будет фрейм данных. Используйте rowSums для суммирования по строкам. (Дух. РЕДАКТИРОВАТЬ: не совсем так, как считалось ранее!) lapply возвращает список, который нам нужно преобразовать во фрейм данных, и, наконец, мы исправляем имена. РЕДАКТИРОВАТЬ: sapply устраняет необходимость в последнем шаге.

 unique_col_names <- unique(colnames(dfr))
new_dfr <- sapply(unique_col_names, function(name)
{
  subs <- dfr[, colnames(dfr) == name]
  if(is.data.frame(subs))
    rowSums(subs)
  else
    subs
})
  

Комментарии:

1. Что касается ‘Duh’: суммы строк действительно суммируются по строкам, но сумма строк суммируется по столбцам 😉

2. спасибо за ответ. Я работал с суммами строк «Duh», это не было главной проблемой моей проблемы! Кроме того, если можно так выразиться, я подумал, что «Duh» — неподходящая «функция» для публикации на этом форуме!;)