Скользящее среднее от первого до конечного значения в столбце - PullRequest
0 голосов
/ 27 сентября 2018

Набор данных состоит из последовательности чисел, как показано ниже.Мне нужен новый столбец, который говорит о среднем движении между первым значением и конечным значением.Например, в первом ряду цифры (1, 3, 5, 2), поэтому среднее движение среднее (abs (3-1), abs (5-1), abs (2-1)), то есть2.333

Sl no Column A req

1 1 > 3 > 5 > 2 2.333

2 2 > 5 > 1 > 10 > 5 3.75

Есть ли способ решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

1) dplyr / tidyr Предполагая, что ввод DF, воспроизводимый в примечании в конце, разделяет Column A на отдельные строки, суммирует его и присоединяет новый столбец req к исходному фрейму данных.

library(dplyr)
library(tidyr)

Req <- DF %>% 
  separate_rows(`Column A`, convert = TRUE) %>% 
  group_by(`Sl no`) %>% 
  summarize(req = mean(abs(`Column A`[-1] - `Column A`[1]))) %>%
  ungroup

DF %>% inner_join(Req)

## Joining, by = "Sl no"
##   Sl no           Column A      req
## 1     1      1 > 3 > 5 > 2 2.333333
## 2     2 2 > 5 > 1 > 10 > 5 3.750000

2) Base R Используется базовое решение R AvgAbsDiff, которое принимает символьную строку в формате Column A, читает ее с использованием scan и вычисляетreq.Затем он применяется к каждой строке.

AvgAbsDiff <- function(x) {
  z <- scan(text = x, sep = ">", quiet = TRUE)
  mean(abs(z[-1] - z[1]))
}  
transform(DF, req = sapply(as.character(`Column A`), AvgAbsDiff), 
  row.names = NULL, check.names = FALSE)

##   Sl no           Column A      req
## 1     1      1 > 3 > 5 > 2 2.333333
## 2     2 2 > 5 > 1 > 10 > 5 3.750000

2a) В этом базовом решении не используются никакие * функции применения.Считайте Column A в кадр данных, используя read.table, а затем вычислите req из этого.

r <- read.table(text = as.character(DF$`Column A`), header = FALSE, 
  sep = ">", fill = NA)
transform(DF, req = rowMeans(abs(r[, -1] - r[, 1]), na.rm = TRUE),
  check.names = FALSE)

##   Sl no           Column A      req
## 1     1      1 > 3 > 5 > 2 2.333333
## 2     2 2 > 5 > 1 > 10 > 5 3.750000

Примечание

DF <-
structure(list(`Sl no` = 1:2, `Column A` = structure(1:2, 
.Label = c("1 > 3 > 5 > 2", 
"2 > 5 > 1 > 10 > 5"), class = "factor")), 
 class = "data.frame", row.names = c(NA, -2L))
0 голосов
/ 27 сентября 2018

Следующий код работает, но он может быть написан лучше.В любом случае ..

Позвольте мне сначала заново создать ваш фрейм данных

q <- data.frame(Sl_no=1:2, Column_A=c(("1 > 3 > 5 > 2"), (" 2 > 5 > 1 > 10 > 5")))
q$req <- NA

, что дает нам:

  Sl_no            Column_A   req
      1       1 > 3 > 5 > 2    NA
      2  2 > 5 > 1 > 10 > 5    NA

Далее, давайте разделим эту последовательность на список R:

q$A <- strsplit(as.character(q$Column_A), " > ")

А также добавьте длину этого списка:

q$A_length <- lengths(q$A)

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

for (row in 1:nrow(q)) {
    sum = c()
    for (number in 2:q$A_length[row]) {
        sum <- c(sum, as.numeric(q$A[[row]][number]) - as.numeric(q$A[[row]][1]))
    }
    q$req[row] <- mean(sum)
 }

Наконец, давайте напечатаем созданный кадр данных:

  Sl_no             Column_A                 A   A_length        req
      1        1 > 3 > 5 > 2        1, 3, 5, 2          4   2.333333
      2   2 > 5 > 1 > 10 > 5    2, 5, 1, 10, 5          5   3.250000

Надеюсь, это поможет!

0 голосов
/ 27 сентября 2018

Вы можете сделать что-то вроде этого:

data$req <- sapply(data$columnA,
                   function(x) mean(abs(diff(as.integer(unlist(strsplit(x, ' > ')))))))

sapply будет применять функцию к каждому элементу columnA.

Затем, работая изнутри наружу: strsplit разбивает элемент в столбце A на ">", в результате чего:

[[1]]
[1] "1" "3" "5" "2"

unlist превратит результат в вектор:

"1" "3" "5" "2"

as.integer для преобразования его в числа:

1 3 5 2

diff для вычисления разностей между числами:

2  2 -3

abs для принятия абсолютных значений:

2 2 3

и, наконец,mean, чтобы взять среднее значение:

2.333333

Редактировать: Немного неправильно прочитать вопрос, это будет правильно рассчитать результат:

my.df$req <- sapply(my.df$columnA,
                    function(x) {
                      tmp <- as.integer(unlist(strsplit(x, ' > ')))
                      mean(abs(tmp[2:length(tmp)] - tmp[1]))
                    })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...