Как добавить столбцы в фрейм данных на основе индексов в R? (См пример) - PullRequest
0 голосов
/ 09 января 2019

Я работаю с самодельной инфиксной функцией, которая просто вычисляет процентный рост между наблюдениями в колонках.

options(digits=3)

`%grow%` <- function(x,y) {
    (y-x) / x * 100
}

test <- data.frame(a=c(101,202,301), b=c(123,214,199), h=c(134, 217, 205))

Затем я использую lapply в своей базе данных игрушек, чтобы добавить два новых столбца.

test[,4:5] <- lapply(1:(ncol(test)-1), function(i) test[,i] %grow% test[,(i+1)])
test

#Output
    a   b   h     V4   V5
1 101 123 134  21.78 8.94
2 202 214 217   5.94 1.40
3 301 199 205 -33.89 3.02

Это легко, учитывая, что у меня всего три столбца, и я могу написать test[,4:5]. Теперь поговорим в общих чертах: как это сделать, если у нас есть n столбцов, использующих индексы столбцов? Я имею в виду, что я хочу создать n-1 столбцов для данной базы данных, начиная с последней. Что-то вроде:

test[,(last_current_column+1):(last_column_created_using_function)]

Учитывая то, что я читал в некоторых других постах, используя мой пример, test[,(last_current_column+1): можно записать как:

test[,(ncol(test)+1):]

но вторая часть все еще отсутствует, и я понятия не имею, как ее написать.

Надеюсь, я ясно дал понять. Я полностью ценю любой комментарий или совет.

Счастливого 2019 года :) 1020 *

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Другой способ будет:

#options(digits=3)

`%grow%` <- function(x,y) {
  (y-x) / x * 100
}

test <- data.frame(a=c(101,202,301), 
                   b=c(123,214,199),
                   h=c(134, 217, 205),
                   d=c(156,234,235))
#     a   b   h   d
# 1 101 123 134 156
# 2 202 214 217 234
# 3 301 199 205 235


seqcols <- seq_along(test) # saved just to improve readability
test[,seqcols[-length(seqcols)] + max(seqcols)] <- lapply(seqcols[-length(seqcols)], 
                     function(i) test[,i] %grow% test[,(i+1)])
test
#     a   b   h   d     V5   V6    V7
# 1 101 123 134 156  21.78 8.94 16.42
# 2 202 214 217 234   5.94 1.40  7.83
# 3 301 199 205 235 -33.89 3.02 14.63

Аналогично второму решению от @Ronak Shah, только с использованием map2_df из purrr:

cbind(test,
      new=purrr::map2_df(test[seqcols[-length(seqcols)]], test[seqcols[-1]], `%grow%`),
      deparse.level=1)
#     a   b   h   d  new.a new.b new.h
# 1 101 123 134 156  21.78  8.94 16.42
# 2 202 214 217 234   5.94  1.40  7.83
# 3 301 199 205 235 -33.89  3.02 14.63
0 голосов
/ 09 января 2019

Вы бы всегда ncol(test) - 1 новые столбцы. Теперь с помощью этой логики есть несколько способов сделать это.

Одним из способов будет создание символьного вектора с некоторым значением префикса.

test[paste0("new_col", seq_len(ncol(test) - 1))] <- lapply(1:(ncol(test)-1),
                    function(i) test[,i] %grow% test[,(i+1)])


test
#    a   b   h   new_col1 new_col2
#1 101 123 134  21.782178 8.943089
#2 202 214 217   5.940594 1.401869
#3 301 199 205 -33.887043 3.015075

Еще один вариант использования mapply и transform путем создания подмножеств кадра данных

transform(test,
   new_col = mapply(`%grow%`, test[1:(ncol(test)- 1)], test[2:ncol(test)]))


#    a   b   h  new_col.a new_col.b
#1 101 123 134  21.782178  8.943089
#2 202 214 217   5.940594  1.401869
#3 301 199 205 -33.887043  3.015075
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...