Выборочная замена столбцов в R их дельта-значениями - PullRequest
0 голосов
/ 02 октября 2009

У меня есть данные, считываемые во фрейм данных R по столбцам. Некоторые из столбцов будут увеличиваться в стоимости; только для этих столбцов я хочу заменить каждое значение (n) на его отличие от предыдущего значения в этом столбце. Например, глядя на отдельный столбец, я хочу

c(1,2,5,7,8)

подлежит замене на

c(1,3,2,1)

чем отличаются последовательные элементы

Однако уже поздно, и я думаю, что мой мозг просто перестал работать. Вот мой код в настоящее время

col1 <- c(1,2,3,4,NA,2,3,1) # This column rises and falls, so we want to ignore it
col2 <- c(1,2,3,5,NA,5,6,7) # Note: this column always rises in value, so we want to replace it with deltas
col3 <- c(5,4,6,7,NA,9,3,5) # This column rises and falls, so we want to ignore it
d <- cbind(col1, col2, col3)
d
fix_data <- function(data) {
    # Iterate through each column...
    for (column in data[,1:dim(data)[2]]) {
        lastvalue <- 0
        # Now walk through each value in the column, 
        # checking to see if the column consistently rises in value
        for (value in column) {
            if (is.na(value) == FALSE) { # Need to ignore NAs
                if (value >= lastvalue) {
                    alwaysIncrementing <- TRUE
                } else {
                    alwaysIncrementing <- FALSE
                    break
                }
            }
        }

        if (alwaysIncrementing) {
            print(paste("Column", column, "always increments"))
        }

        # If a column is always incrementing, alwaysIncrementing will now be TRUE
        # In this case, I want to replace each element in the column with the delta between successive
        # elements.  The size of the column shrinks by 1 in doing this, so just prepend a copy of
        # the 1st element to the start of the list to ensure the column length remains the same
        if (alwaysIncrementing) {
            print(paste("This is an incrementing column:", colnames(column)))
            column <- c(column[1], diff(column, lag=1))
        }
    }
    data
}

fix_data(d)
d

Если вы скопируете / вставите этот код в RGui, вы увидите, что он ничего не делает с предоставленным фреймом данных.

Кроме того, что сошел с ума, что я делаю не так?

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

Ответы [ 2 ]

3 голосов
/ 02 октября 2009

Не обращаясь к коду в деталях, вы присваиваете значения column, который является локальной переменной в цикле (т. Е. В этом контексте нет связи между column и data). Вам необходимо присвоить эти значения соответствующему значению в data.

Кроме того, data будет локальным для вашей функции, поэтому вам нужно присвоить его обратно data после запуска функции.

Кстати, вы можете использовать diff, чтобы увидеть, увеличивается ли какое-либо значение, а не зацикливается ли каждое значение:

idx <- apply(d, 2, function(x) !any(diff(x[!is.na(x)]) < 0))
d[,idx] <- blah
2 голосов
/ 02 октября 2009

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

dfr <- data.frame(x = c(1,2,5,7,8), y = (1:5)^2)
as.data.frame(lapply(dfr, diff))

  x y
1 1 3
2 3 5
3 2 7
4 1 9

РЕДАКТИРОВАТЬ: Я только заметил еще несколько вещей. Вы используете матрицу, а не фрейм данных (как вы указали в вопросе). Для вашей матрицы 'd' вы можете использовать

d_diff <- apply(d, 2, diff)
#Find columns that are (strictly) increasing
incr <- apply(d_diff, 2, function(x) all(x > 0, na.rm=TRUE))
#Replace values in the approriate columns
d[2:nrow(d),incr] <- d_diff[,incr]
...