Добавление значений двух строк и сохранение их в другом столбце с повторением

У меня есть такой фрейм данных

x1<- c(0,1,1,1,1,0)

df<-data.frame(x1)

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

Здесь вы можете видеть, что сумма первых двух строк равна 1, и она указана в первых двух строках нового столбца (x2). Далее сумма третьей и четвертой строк дается в 3-й и четвертой строке нового столбца. Кто-нибудь может помочь?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
146
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Создайте индекс с gl для каждых 2 строк и выполните суммирование после группировки.

library(dplyr)
df <- df %>%
    group_by(grp = as.integer(gl(n(), 2, n()))) %>% 
    mutate(x2 = sum(x1)) %>% 
    ungroup %>% 
    select(-grp)

-выход

df
# A tibble: 6 × 2
     x1    x2
  <dbl> <dbl>
1     0     1
2     1     1
3     1     2
4     1     2
5     1     1
6     0     1

Или с помощью collapse/data.table

library(data.table)
library(collapse)
setDT(df)[, x2 := fsum(x1, g = rep(.I, each = 2, length.out = .N), TRA = 1)]

-выход

> df
      x1    x2
   <num> <num>
1:     0     1
2:     1     1
3:     1     2
4:     1     2
5:     1     1
6:     0     1

Интересное решение; Я никогда раньше не слышал о gl.

Vinícius Félix 27.11.2022 19:07

Вот способ использования dplyr, где я создаю вспомогательный столбец для группировки

library(dplyr)


x1<- c(0,1,1,1,1,0)

df <- data.frame(x1)

len_df <- nrow(df)
aux <- rep(seq(1:(len_df/2)),each = 2)[1:len_df]

df %>% 
  mutate(aux = aux) %>% 
  group_by(aux) %>% 
  mutate(x2 = sum(x1)) %>% 
  ungroup() %>%
  select(-aux)

# A tibble: 6 x 2
     x1    x2
  <dbl> <dbl>
1     0     1
2     1     1
3     1     2
4     1     2
5     1     1
6     0     1

Однако столбец «aux» остается во фрейме данных.

P Initiate 27.11.2022 19:09

о... вы можете использовать select(-aux), чтобы удалить его

Vinícius Félix 27.11.2022 19:13
Ответ принят как подходящий

Вы можете определить группы, используя деление этажей, а затем просто получить сгруппированную сумму:

library(dplyr)

df %>%
  mutate(group = (row_number() - 1) %/% 2) %>%
  group_by(group) %>%
  mutate(x2 = sum(x1)) %>%
  ungroup() %>%
  select(-group)
# # A tibble: 6 × 2
#      x1    x2
#   <dbl> <dbl>
# 1     0     1
# 2     1     1
# 3     1     2
# 4     1     2
# 5     1     1
# 6     0     1

Во-первых, способ создания data.frame без промежуточной переменной.

Это разбивает data.frame на группы по 2, суммирует, а затем повторяет шаблон в новую переменную.

df<-data.frame(x1=c(0,1,1,1,1,0))

df$x2<-rep(lapply(split(df, rep(1:3, each=2)), sum), each=2)

#  x1 x2
#1  0  1
#2  1  1
#3  1  2
#4  1  2
#5  1  1
#6  0  1

в базе R вы можете сделать:

 transform(df,x2 = ave(x1, gl(nrow(df)/2, 2), FUN = sum))

  x1 x2
1  0  1
2  1  1
3  1  2
4  1  2
5  1  1
6  0  1

Вы можете использовать ave + ceiling (обе являются базовыми функциями R)

> transform(df, x2 = ave(x1, ceiling(seq_along(x1) / 2)) * 2)
  x1 x2
1  0  1
2  1  1
3  1  2
4  1  2
5  1  1
6  0  1

Еще несколько вариантов с избранными бенчмарками.

x1 <- sample(0:1, 1e4, 1)

microbenchmark::microbenchmark(
  matrix = rep(colSums(matrix(x1, 2)), each = 2),
  recycle = x1 + x1[seq(x1) + c(1, -1)],
  cumsum = rep(diff(cumsum(c(0, x1))[seq(1, length(x1) + 1, 2)]), each = 2),
  Thomas = ave(x1, ceiling(seq_along(x1)/2))*2,
  onyambu = ave(x1, gl(length(x1)/2, 2), FUN = sum),
  check = "equal"
)
#> Unit: microseconds
#>     expr       min         lq        mean     median         uq       max neval
#>   matrix    65.001    69.6510    79.27203    78.4510    82.1510   148.501   100
#>  recycle    95.001   100.6505   108.65003   107.5510   110.6010   176.901   100
#>   cumsum   137.201   148.9010   169.61090   166.5505   177.7015   340.002   100
#>   Thomas 24645.401 25297.2010 26450.46994 25963.3515 27463.2010 31803.101   100
#>  onyambu  3774.902  3935.7510  4444.36500  4094.3520  4336.1505 11070.301   100

С data.table для больших данных:

library(data.table)
library(collapse)

x1 <- sample(0:1, 1e6, 1)
df <- data.frame(x1)

microbenchmark::microbenchmark(
  matrix = setDT(df)[, x2 := rep(colSums(matrix(x1, 2)), each = 2)],
  recycle = setDT(df)[, x2 := x1 + x1[.I + c(1, -1)]],
  akrun = setDT(df)[, x2 := fsum(x1, g = rep(.I, each = 2, length.out = .N), TRA = 1)],
  check = "identical"
)
#> Unit: milliseconds
#>     expr       min        lq     mean    median       uq     max neval
#>   matrix  8.053302  8.937301 10.64786  9.376551 12.51890 17.2037   100
#>  recycle 12.117101 12.965950 16.57696 14.003151 17.09805 56.4729   100
#>    akrun 10.071701 10.611051 14.42578 11.291601 14.79090 55.1141   100

Другие вопросы по теме