Создайте функцию, которая выполняет итерацию по столбцам фрейма данных

У меня есть wide formatdataframe, который расположен на основе минимального значения для каждого column (от высокого к низкому). Наибольшее минимальное значение — это column 1, а наименьшее минимальное значение — это last column. Я хочу добиться того, чтобы минимальное значение каждого column совпадало с позицией соответствующего значения в следующем column и так далее.

Вот пример dataframe:

library(tidyverse)
library(data.table)

MA_vol <- c(0.2486667, 0.2463333, 0.2426667, 0.2423333, 0.2376667, 0.2323333, 0.2270000, 0.2246667, 0.2216667, 0.2203333, 0.2183333, 0.2126667, 0.2076667, 0.2060000)
R_id <- rep(15, length(MA_vol))
df1 <- data.frame(R_id, MA_vol)

MA_vol <- c(0.2073333, 0.2053333, 0.2013333, 0.1993333, 0.1973333, 0.1970000, 0.1966667, 0.1946667, 0.1920000, 0.1890000, 0.1883333, 0.1866667, 0.1843333, 0.1823333, 0.1810000)
R_id <- rep(13, length(MA_vol))
df2 <- data.frame(R_id, MA_vol)

MA_vol <- c(0.2016667, 0.1996667, 0.1980000, 0.1970000, 0.1963333, 0.1956667, 0.1930000, 0.1913333, 0.1900000, 0.1893333, 0.1890000, 0.1863333, 0.1853333, 0.1820000, 0.1800000, 0.1780000, 0.1763333)
R_id <- rep(4, length(MA_vol))
df3 <- data.frame(R_id, MA_vol)

MA_vol <- c(0.2180000, 0.2146667, 0.2126667, 0.2103333, 0.2070000, 0.2040000, 0.2010000, 0.1993333, 0.1956667, 0.1950000, 0.1926667, 0.1920000, 0.1896667, 0.1890000, 0.1856667, 0.1830000, 0.1786667, 0.1763333, 0.1733333, 0.1720000, 0.1700000, 0.1686667, 0.1670000)
R_id <- rep(8, length(MA_vol))
df4 <- data.frame(R_id, MA_vol)

MA_vol <- c(0.2096667, 0.2063333, 0.2030000, 0.1993333, 0.1953333, 0.1916667, 0.1880000, 0.1870000, 0.1850000, 0.1830000, 0.1783333, 0.1753333, 0.1726667, 0.1716667, 0.1673333, 0.1666667, 0.1656667) 
R_id <- rep(2, length(MA_vol))
df5 <- data.frame(R_id, MA_vol)

df <- bind_rows(df1, df2, df3, df4, df5)

# Order based on each min value (high to low)
R_minvalues <- df %>%
  group_by(R_id) %>%                # group by recession id
  slice(which.min(MA_vol)) %>%      # extract min volume values for each recession
  select(R_id, MA_vol)

x <- R_minvalues[with(R_minvalues, order(-MA_vol)), ]     # order by MA-vol min value (high to low)
R_id_order <- as.numeric(x$R_id)

# Reorder dataframe based on R_minvalues (high to low)
MRC_DF <- df %>%
  arrange(match(R_id, R_id_order)) %>%       # match R_id rows with R_id_order
  transform(t = 1:nrow(df)) %>%     # create t (time) column the length of the df
  select(t, R_id, MA_vol)                    # select columns

R_order_chr <- as.character(R_id_order)     # convert R_id_order to character so can rearrange columns

MRC_DF_wide <- dcast(setDT(MRC_DF), t ~ R_id, value.var = "MA_vol") %>%     # convert df to wide format 
  select(all_of(R_order_chr))       # rearrange column order

colnames(MRC_DF_wide)[1:ncol(MRC_DF_wide)] <-
  paste("R", colnames(MRC_DF_wide)[1:ncol(MRC_DF_wide)], sep = "")     # add "R_" to start of numbers so syntax is correct

Следующий код дает желаемый результат, но он обрабатывает только один столбец за раз и требует ручного ввода (укажите имя столбца):

# identify positional index of minimum value and corresponding closest value in next column 
a <- which.min(MRC_DF_wide$R15)     # position of min value in 1st column 
b <-
  which.min(abs(MRC_DF_wide$R13 - min(MRC_DF_wide$R15, na.rm = TRUE)))     # position of closest value in 2nd column 
                # 2nd column           # 1st column

c <- b - a     # positional index difference 

# shift column rows up 
shift <- function(x, n){
  c(x[-(seq(n))], rep(NA, n))
}

MRC_DF_wide$R13 <- shift(MRC_DF_wide$R13, c)     # shift 2nd column up by positional index difference 

Я хотел бы создать функцию, которая перебирает столбцы 1 и 2, затем 2 и 3 и так далее для ncol из dataframe. Это моя попытка выделить идентификатор столбца, но она не увенчалась успехом:

matching.strip.fn <- function(df) {
  min_index <- which.min(df[[i]])     # positional index of min value in 1st column
  match_index <- which.min(abs(df[[i+1]] - min(df[[i]], na.rm = TRUE)))     # positional index of closest value in 2nd column
                            # 2nd column       1st column 
  index_diff <- match_index - min_index     # positional index difference 
  
  df$i + 1 <- c(df[-(seq(index_diff))], rep(NA, index_diff))     # shift values up by positional difference in 2nd column 
# 2nd column
}

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

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

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

Ответы 1

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

Я думаю, вы можете легко решить эту проблему с помощью purrr::accumulate():

accumulate(MRC_DF_wide, \(.x, .y) {
  .y <- .y[!is.na(.y)]
  pos <- which.min(.x) - which.min(abs(min(.x, na.rm = T) - .y))
  c(rep(NA, pos), .y, rep(NA, length(.x) - pos - length(.y)))
})  |>
  set_names(names(MRC_DF_wide)) |>
  as.data.frame() %>%
  filter(apply(., 1, \(x) ! all(is.na(x))))
#>          R15       R13        R4        R8        R2
#> 1  0.2486667        NA        NA        NA        NA
#> 2  0.2463333        NA        NA        NA        NA
#> 3  0.2426667        NA        NA        NA        NA
#> 4  0.2423333        NA        NA        NA        NA
#> 5  0.2376667        NA        NA        NA        NA
#> 6  0.2323333        NA        NA        NA        NA
#> 7  0.2270000        NA        NA        NA        NA
#> 8  0.2246667        NA        NA        NA        NA
#> 9  0.2216667        NA        NA        NA        NA
#> 10 0.2203333        NA        NA        NA        NA
#> 11 0.2183333        NA        NA        NA        NA
#> 12 0.2126667        NA        NA        NA        NA
#> 13 0.2076667 0.2073333        NA 0.2180000        NA
#> 14 0.2060000 0.2053333 0.2016667 0.2146667        NA
#> 15        NA 0.2013333 0.1996667 0.2126667        NA
#> 16        NA 0.1993333 0.1980000 0.2103333        NA
#> 17        NA 0.1973333 0.1970000 0.2070000        NA
#> 18        NA 0.1970000 0.1963333 0.2040000        NA
#> 19        NA 0.1966667 0.1956667 0.2010000        NA
#> 20        NA 0.1946667 0.1930000 0.1993333        NA
#> 21        NA 0.1920000 0.1913333 0.1956667 0.2096667
#> 22        NA 0.1890000 0.1900000 0.1950000 0.2063333
#> 23        NA 0.1883333 0.1893333 0.1926667 0.2030000
#> 24        NA 0.1866667 0.1890000 0.1920000 0.1993333
#> 25        NA 0.1843333 0.1863333 0.1896667 0.1953333
#> 26        NA 0.1823333 0.1853333 0.1890000 0.1916667
#> 27        NA 0.1810000 0.1820000 0.1856667 0.1880000
#> 28        NA        NA 0.1800000 0.1830000 0.1870000
#> 29        NA        NA 0.1780000 0.1786667 0.1850000
#> 30        NA        NA 0.1763333 0.1763333 0.1830000
#> 31        NA        NA        NA 0.1733333 0.1783333
#> 32        NA        NA        NA 0.1720000 0.1753333
#> 33        NA        NA        NA 0.1700000 0.1726667
#> 34        NA        NA        NA 0.1686667 0.1716667
#> 35        NA        NA        NA 0.1670000 0.1673333
#> 36        NA        NA        NA        NA 0.1666667
#> 37        NA        NA        NA        NA 0.1656667

Created on 2022-03-21 by the reprex package (v2.0.1)

Привет @shs, спасибо за ответ. Как мне адаптировать код, чтобы минимальное значение совпадало с ближайшим значением в следующем столбце? Например, столбец R8 min.value = 0,167, поэтому значения в столбце R2 должны быть смещены вниз, чтобы значение 0,1673 находилось в той же строке. Если бы вы могли предоставить более подробную информацию о шаге накопления, это помогло бы моему пониманию, спасибо.

mrob27 21.03.2022 16:33

Я отредактировал код, чтобы он соответствовал вашему разъяснению правила выравнивания. Простую иллюстрацию того, как работает аккумулирование, можно найти на странице внизу справа на второй странице шпаргалки по мурлыке. Для более подробного объяснения вы можете прочитать соответствующий подраздел Advanced R Хэдли Уикхема

shs 21.03.2022 17:03

Вероятно, это из-за версии R (не RStudio). В R 4.1 представлены родные конвейеры |> и сокращенные функции \(...) ....

shs 22.03.2022 12:06

Спасибо за вашу помощь, как вы сказали, неожиданные токены ошибок были из-за версии R, а не RStudio.

mrob27 22.03.2022 12:23

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