Я новичок в 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.
@neilfws мне кажется, что код Stata зацикливается на столбцах, поэтому замена может быть чем-то вроде dplyr::mutate_at()
.
Спасибо. Да, @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)
Если вы введете небольшой образец своего набора данных (см. stackoverflow.com/questions/5963269/…), мы сможем вам лучше помочь.
@ Аарон Спасибо. Я добавил простые образцы в вопрос.
Для справки, ваш последний пример Stata должен использовать egen
, а не gen
(что означает generate
).
Итак, несколько вариантов здесь. Я настоятельно рекомендую добавить несколько примеров данных, чтобы мы могли лучше вам помочь. В зависимости от того, что вы делаете, вы можете сделать несколько вещей:
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"))
}
Спасибо за ответ. Но, как сказал Мариус, я хотел бы зацикливаться на столбце, а не на строке. Я отредактировал свой вопрос и привел несколько примеров. Надеюсь, это сделает мой вопрос более ясным.
Есть много разных способов сделать такие вещи. Например. для примера роста, веса, ИМТ вы можете сделать это в основном так же, как в 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)
.
Да: paste0("var", 1:27)
создаст полный вектор имен столбцов.
Перекодирование нескольких переменных одновременно
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
Вам, вероятно, не понадобятся циклы for для выполнения любого из этих действий в R; соответствующие функции, скорее всего, векторизованный.