#r #dataframe #sapply
#r #фрейм данных #сапфировый
Вопрос:
Мой фрейм данных выглядит так:
x s1 s2 s3 s4 1 x1 1 1954 1 yes 2 x2 2 1955 1 no 3 x3 1 1976 2 yes 4 x4 2 1954 2 yes 5 x5 3 1943 1 no
Примеры данных:
df lt;- data.frame(x=c('x1','x2','x3','x4','x5'), s1=c(1,2,1,2,3), s2=c(1954,1955,1976,1954,1943), s3=c(1,1,2,2,1), s4=c('yes','no','yes','yes','no'))```
Можно ли извлечь столбцы фрейма данных, содержащие целые 1
числа, в 3
? Например, новый фрейм данных будет выглядеть следующим образом:
newdf x s1 s3 1 x1 1 1 2 x2 2 1 3 x3 1 2 4 x4 2 2 5 x5 3 1
Можно ли изменить столбцы s1
и s3
на 0 или 1 в зависимости от того, равно ли значение в столбце 1 или нет? Измененный фрейм данных будет выглядеть следующим образом:
newdf2 x s1 s3 1 x1 1 1 2 x2 0 1 3 x3 1 0 4 x4 0 0 5 x5 0 1
Комментарии:
1. Вы говорите, что хотите извлечь столбцы, содержащие целые числа от 1 до 3, но затем сохраняете
x
переменную, содержащую строковые данные-хотите ли вы, чтобы там было другое правило? (Илиx
переменная-это просто специальная переменная, которую вы хотите сохранить?)2. Переменная x — это просто особая переменная, которую я хотел бы сохранить!
Ответ №1:
основание R
newdf lt;- df[, unique(c("x", names(which(sapply(df, function(z) is.numeric(z) amp; any(c(1, 3) %in% z)))))), drop = FALSE] newdf # x s1 s3 # 1 x1 1 1 # 2 x2 2 1 # 3 x3 1 2 # 4 x4 2 2 # 5 x5 3 1 newdf[-1] lt;- lapply(newdf[-1], function(z) (z == 1)) newdf # x s1 s3 # 1 x1 1 1 # 2 x2 0 1 # 3 x3 1 0 # 4 x4 0 0 # 5 x5 0 1
Проходной:
- сначала мы определяем, какие столбцы являются числами и содержат числа 1 или 3:
sapply(df, function(z) is.numeric(z) amp; any(c(1, 3) %in% z)) # x s1 s2 s3 s4 # FALSE TRUE FALSE TRUE FALSE
Это исключит любой столбец, который не является числовым, что означает, что
character
столбец, содержащий литерал"1"
или"3"
не будет сохранен. Это полный вывод с моей стороны; если вы хотите принять строковые версии, удалитеis.numeric(z)
компонент. - во-вторых, мы извлекаем имена тех, которые являются истинными, и добавляем
"x"
c("x", names(which(sapply(df, function(z) is.numeric(z) amp; any(c(1, 3) %in% z))))) # [1] "x" "s1" "s3"
- оберните это,
unique(.)
если по какой-то причине"x"
оно также числовое и содержит 1 или 3 (этот шаг является чисто оборонительным, он может вам не понадобиться). - выберите эти столбцы, защитно добавив
drop=FALSE
, чтобы, если сопоставлен только один столбец, он все равно возвращал полныйdata.frame
- замените только эти столбцы (исключая первый столбец, который является
"x"
) на 0 или 1;z == 1
возвратlogical
и перенос(..)
преобразуют логику в 0 (ложь) или 1 (истина).
dplyr
library(dplyr) df %gt;% select(x, where(~ is.numeric(.) amp; any(c(1, 3) %in% .))) %gt;% mutate(across(-x, ~ (. == 1))) # x s1 s3 # 1 x1 1 1 # 2 x2 0 1 # 3 x3 1 0 # 4 x4 0 0 # 5 x5 0 1
Ответ №2:
Я думаю, что это то, чего вы ожидали :
my_df lt;- data.frame(x=c('x1','x2','x3','x4','x5'), s1=c(1,2,1,2,3), s2=c(1954,1955,1976,1954,1943), s3=c(1,1,2,2,1), s4=c('yes','no','yes','yes','no')) my_df$end lt;- apply(my_df, 2, function(x) paste(x, collapse = " ")) my_df lt;- my_df %gt;% group_by(x) %gt;% mutate(end2 = paste(str_extract_all(string = end, pattern = "1|2|3", simplify = TRUE), collapse = " ")) my_var lt;- which(my_df$end == my_df$end2) my_df[, my_var] lt;- t(apply(my_df[, my_var], 1, function(x) ifelse(test = x == 1, yes = 1, no = 0))) my_df lt;- my_df[, c(1, my_var)]