Как я могу сделать что-то вроде foreach в Stata, используя R?

Я новичок в R и использую Stata. Я могу перебирать переменные, используя foreach и forvalue в Stata.

Я хотел бы перебирать столбец, а не перебирать строку. Например, у меня есть столбец с именем var1, var2, var3. И данные, как показано ниже:

var1 var2 var3
  1    1   1   
  2   999  3
 999   2  999

Я хотел бы перекодировать все значения «999» в переменных на отсутствующие. В Стате я могу сделать

forvalue i = 1(1)3{
  replace var`i'  = "NA" if var`i' = = "999"
}

Поэтому у меня есть результат, как

var1 var2 var3
  1    1   1   
  2   NA   3
  NA   2  NA

Кроме того, если у меня есть столбец с именем ht, wgt, bmi, я хотел бы рассчитать среднее значение столбца и сохранить его в новом столбце с соответствующим именем. Набор данных выглядит следующим образом:

 ht     wgt   bmi
154.5  43.1 18.1
164.2  63   23.4

В Стате я могу сделать

foreach i of varlist ht wgt bmi{
  gen `i'mean = mean(`i')
}

И будет результат

 ht    wgt   bmi  htmean wgtmean bmimean
154.5  43.1 18.1  159.35  53.05   20.75
164.2  63   23.4  159.35  53.05   20.75

Я понятия не имею, как это сделать с помощью R.

Вам, вероятно, не понадобятся циклы for для выполнения любого из этих действий в R; соответствующие функции, скорее всего, векторизованный.

neilfws 29.05.2019 03:42

@neilfws мне кажется, что код Stata зацикливается на столбцах, поэтому замена может быть чем-то вроде dplyr::mutate_at().

Marius 29.05.2019 03:45

Спасибо. Да, @Marius, я бы хотел перебирать столбец, а не строку. Я пытался использовать mutate_at() . Однако он дает комментарий Evaluation error: replacement has 0 rows, data has 1492. Мой код таков: f1 <- function(x) dat$x[dat$x==999] <-NA dat <- mutate_at(dat,vars(var1:var21), f1)

kmY 29.05.2019 04:27

Если вы введете небольшой образец своего набора данных (см. stackoverflow.com/questions/5963269/…), мы сможем вам лучше помочь.

Aaron left Stack Overflow 29.05.2019 04:45

@ Аарон Спасибо. Я добавил простые образцы в вопрос.

kmY 29.05.2019 05:02

Для справки, ваш последний пример Stata должен использовать egen, а не gen (что означает generate).

Nick Cox 29.05.2019 10:51
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
1 893
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

library(dplyr)
mtcars %>% 
    mutate(my_hp = case_when(
        hp<50~"Small",
        hp < 100~"Medium",
        TRUE~"Large"
    ))

Это относится к условной логике: используйте функцию mutate для создания новой переменной (столбца) и функцию case_when для использования в разных случаях в зависимости от значения hp.

Кроме того, вы можете использовать базовый подход R, который может выглядеть как

mtcars$my_hp <- ifelse(mtcars$hp < 50, "Small",
                                             ifelse(mtcars$hp< 100, "Medium",
                                                         "Large"))

Итак, в этом случае вы создаете новое значение, называемое my_hp, используя цепочку операторов ifelse, которые проверяют условие.

И если вы абсолютно хотите сделать цикл, что вам не нужно делать в этом случае, вы можете сделать что-то вроде:

for( i in 1:nrow(mtcars)){
    mtcars$my_hp[i] <- ifelse(mtcars$hp[i] < 50, "Small",
                                                            ifelse(mtcars$hp[i]< 100, "Medium",
                                                                         "Large"))

}

Спасибо за ответ. Но, как сказал Мариус, я хотел бы зацикливаться на столбце, а не на строке. Я отредактировал свой вопрос и привел несколько примеров. Надеюсь, это сделает мой вопрос более ясным.

kmY 29.05.2019 04:24
Ответ принят как подходящий

Есть много разных способов сделать такие вещи. Например. для примера роста, веса, ИМТ вы можете сделать это в основном так же, как в Stata, используя цикл for:

# For-loop approach
for (col in c("ht", "wgt", "bmi")) {
    new_col = paste0(col, "_mean")
    df2[, new_col] = mean(df2[, col])
}

Разница в том, что в R существует более сильное разделение между символами в коде и строками, поэтому вы указываете имена столбцов в виде строк, используете paste0 для создания строк, представляющих новые имена столбцов, а затем добавляете их в фрейм данных.

Другой способ сделать это — использовать пакет dplyr и функцию mutate_at, которая применит одно и то же преобразование к нескольким столбцам:

library(dplyr)

df2 %>%
    mutate_at(c("ht", "wgt", "bmi"), 
              list(mean = ~ mean(.)))

Синтаксис немного хитрый: сначала мы даем имена столбцам, затем следующий аргумент показывает, как мы хотим преобразовать столбцы. . является заполнителем для текущего столбца, ~ означает, что R не будет сразу пытаться вычислить mean(.), а будет ждать, пока у нас не будет фактических значений для замены. Когда мы используем список и даем имя преобразованию, например list(transform = ~ . + 2), dplyr автоматически использует имя в качестве суффикса, поэтому вы получаете имена столбцов, такие как x_transform, y_transform и т. д.

Большое спасибо. Оба метода работают хорошо. Как насчет перебора столбцов с именами var1, var2, var3? Поскольку у меня есть 27 столбцов с такими именами, я хотел бы знать, есть ли лучший способ написать код, чем писать c("var1", "var2", "var3", "var4",......"var27).

kmY 29.05.2019 06:48

Да: paste0("var", 1:27) создаст полный вектор имен столбцов.

Marius 29.05.2019 06:51

Перекодирование нескольких переменных одновременно

I would like to recode all "999" values in the variables to missing. In Stata, I can do

forvalue i = 1(1)3{
  replace var`i'  = "NA" if var`i' = = "999"
}

(Для полноты) Вы также можете перекодировать несколько переменных, используя lapply.

Функция lapply() принимает набор переменных и применяет функцию, например. ifelse к этому. Вам нужно указать набор данных и переменные, используя поднастройку [], например. data[,variables].
Затем вы определяете, что вы хотите сделать, это может быть любая перекодировка и т. д., использующая переменную. Функция начинается с определения чего-то похожего на локальный «i» в цикле Stata: function(var), здесь var будет иметь ту же роль, что и i. Наконец, вам нужно сказать, куда идет результат lapply, то есть в новые или перекодированные переменные, снова используя data[,variables].

Вот пример:

# Example data
data <- data.frame(
  var1 = c( 1,2,999),
  var2 = c(1,999,2),
  var3 = c(1,3,999)
)

# Object with the names of the variables you like to recode.
vars_to_recode <- c("var1","var2","var3")

# Recoding
data[ ,vars_to_recode] <- lapply(data[ ,vars_to_recode],
                                      function(var)
                                        ifelse(var == 999, NA, var)
                                      )
data

#    var1 var2 var3
# 1    1    1    1
# 2    2   NA    3
# 3   NA    2   NA

То, что это делает, на самом деле ближе к Stata replace, поскольку исходные переменные заменяются преобразованной переменной.

Альтернативой lapply является map() из пакета purrr, но особенно для программирования я (в настоящее время) предпочитаю базовую функцию R.

Новые переменные, содержащие среднее значение старых переменных

Вторая часть вопроса, на который также можно ответить с помощью lapply, заключается в том, как получить переменные, содержащие средства других. Из исходного вопроса:

Also, if I have column named ht, wgt, bmi, I would like to calculate the mean of the column and store the mean in new column with respective name. In Stata, I can do

foreach i of varlist ht wgt bmi{
  gen `i'mean = mean(`i')
}

Решение с использованием lapply simple вычисляет среднее значение и помещает его в новую переменную/столбец. Это работает, потому что R автоматически заполняет любой столбец («вектор») до длины фрейма данных (так называемая «переработка»).

Пример данных

df <- data.frame(
      id  = 1:2,
      ht  = c(154.5,164.2),
      wgt = c(43.1 ,63),
      bmi = c(18.1 ,23.4))

Определите переменные, которые вы хотите изменить, и имена для новых переменных.

vars <- names(df[,2:4])

# Names for new variables
newvars <- paste(names(df),"_mean")
newvars
# [1] "ht _mean"  "wgt _mean" "bmi _mean"

Создайте новые переменные, содержащие средние значения интересующих переменных:

df[,newvars] <- lapply(df[,vars], 
                       function(var)
                           mean(var)
                       )

Результат:

df

#   ht  wgt  bmi ht _mean wgt _mean bmi _mean
# 1 154.5 43.1 18.1   159.35     53.05     20.75
# 2 164.2 63.0 23.4   159.35     53.05     20.75

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

Похожие вопросы