Self_function не может работать - невозможно создать подгруппу столбцов после конца

Существует фрейм данных raw_df, как показано ниже:

library(tidyverse)

detail <- data.frame(cat = c("a","a","a","b","b","b","b","c","c"),
                     single_amount = c(1,3,7,2,1,4,6,1,6))
    
total <- data.frame(cat = c("a","b","c"),
                    total_amount = c(20,10,9))
    
raw_df <- detail %>% left_join(total, by = 'cat')

Я определил функцию self allocate_data_m для выделения total_amount, когда cumsum(single_data) меньше total_amount

allocate_data_m <- function(data, single_data, total_data) {
  out <- cumsum_single_data <- rep('NA', nrow(data))
  for (grouprow in seq_len(nrow(data))) {
    
    cumsum_single_data[grouprow] <- 
      if_else(grouprow == 1, data[grouprow, single_data],
              cumsum_single_data[grouprow-1] + data[grouprow, single_data])
    
    out[grouprow] <- if_else(cumsum_single_data[grouprow] < data[grouprow, total_data], data[grouprow, single_data], 0)
  }
    out 
}

при запуске allocate_data_m в mutate возникает ошибка. Кто-нибудь может помочь? Спасибо!

raw_df %>%
  group_by(cat) %>%
  mutate(amount_x_all = allocate_data_m(cur_data(), single_amount, total_amount))

Желаемый результат показан ниже, мне просто интересно, почему функция allocate_data_m не может работать.

raw_df %>%
  group_by(cat) %>%
  mutate(amount_x_all = if_else(cumsum(single_amount) < total_amount, single_amount, 0))

Каков ваш ожидаемый результат на основе ваших тестовых данных?

Limey 27.04.2024 10:17

Вы пытаетесь ссылаться на несуществующие столбцы ваших данных. Ошибки находятся в вашем первом утверждении if_else.

Edward 27.04.2024 10:18

@Эдвард Спасибо. В изменяемой переменной single_amount совпадает с Single_data, который находится в функции. Мне интересно, как возникает ошибка и как ее исправить?

anderwyang 27.04.2024 10:38

@Limey Спасибо, я отредактировал сообщение и добавил желаемый результат.

anderwyang 27.04.2024 10:46
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Минимальная доработка вашей функции:

  1. Замените "NA" на NA. Первое представляет собой буквальную строку символов, а второе относится к отсутствующему значению в R.
  2. Замените первый ifelse() на if (...) {...} else {...}. В противном случае cumsum_single_data[grouprow-1] выдаст ошибку, когда grouprow равно 1.
  3. Переместите второй ifelse() за пределы цикла for, поскольку его можно вычислить векторно.
allocate_data_m <- function(single_data, total_data) {
  cumsum_single_data <- rep(NA, length(single_data))
  for (grouprow in seq_len(length(single_data))) {
    cumsum_single_data[grouprow] <- if (grouprow == 1) {
      single_data[grouprow]
    } else {
      cumsum_single_data[grouprow-1] + single_data[grouprow] 
    }
  }
  out <- ifelse(cumsum_single_data < total_data, single_data, 0)
  out 
}
raw_df %>%
  group_by(cat) %>%
  mutate(amount_x_all = allocate_data_m(single_amount, total_amount)) %>%
  ungroup()

# # A tibble: 9 × 4
#   cat   single_amount total_amount amount_x_all
#   <chr>         <dbl>        <dbl>        <dbl>
# 1 a                 1           20            1
# 2 a                 3           20            3
# 3 a                 7           20            7
# 4 b                 2           10            2
# 5 b                 1           10            1
# 6 b                 4           10            4
# 7 b                 6           10            0
# 8 c                 1            9            1
# 9 c                 6            9            6

Версия 2

Используйте имена столбцов вместо векторов-столбцов. В этом случае вы должны использовать имена столбцов в двойных кавычках при вызове allocate_data_m() внутри mutate().

allocate_data_m <- function(data, single_data, total_data) {
  if (is(data, "tbl")) data <- as.data.frame(data)
  cumsum_single_data <- rep(NA, nrow(data))
  for (grouprow in seq_len(nrow(data))) {
    cumsum_single_data[grouprow] <- if (grouprow == 1) {
      data[grouprow, single_data]
    } else {
      cumsum_single_data[grouprow-1] + data[grouprow, single_data]   
    }
  }
  out <- ifelse(cumsum_single_data < data[, total_data], data[, single_data], 0)
  out
}

raw_df %>%
  group_by(cat) %>%
  mutate(amount_x_all = allocate_data_m(cur_data(), "single_amount", "total_amount")) %>%
  ungroup()

Спасибо, это здорово! в вашем коде «single_data» и «total_data» являются векторными? В моем коде строка для имен переменных, я не знаю, почему она не работает.

anderwyang 27.04.2024 11:24

@anderwyang, см. мою обновленную версию 2. В этом случае при вызове allocate_data_m() вам нужно использовать имена столбцов, заключенные в двойные кавычки.

Darren Tsai 28.04.2024 13:11

, спасибо за ваши две версии, очень полезно!

anderwyang 29.04.2024 09:09

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