У меня есть фрейм данных, который выглядит так:
library(tibble)
df_of_measures <-
tribble(~measure, ~meter, ~cubic_ft, ~milliliter, ~mile, ~kilogram, ~pound,
"volume", FALSE, TRUE, TRUE, FALSE, FALSE, FALSE,
"distance", TRUE, FALSE, FALSE, TRUE, FALSE, FALSE,
"mass", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE)
## measure meter cubic_ft milliliter mile kilogram pound
## <chr> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
## 1 volume FALSE TRUE TRUE FALSE FALSE FALSE
## 2 distance TRUE FALSE FALSE TRUE FALSE FALSE
## 3 mass FALSE FALSE FALSE FALSE TRUE TRUE
Я хочу взять столбец measure
и скрестить его значения с другими заголовками, чтобы получить вектор только для комбинаций TRUE
:
[1] "volume_cubic_ft" "volume_milliliter" "distance_meter" "distance_mile" "mass_kilogram" "mass_pound"
Если бы я не пытался обусловить такую операцию тем, является ли она TRUE
или FALSE
, я бы сделал:
as.vector(outer(df_of_measures$measure, names(df_of_measures)[-1], paste, sep = "_"))
## [1] "volume_meter" "distance_meter" "mass_meter" "volume_cubic_ft" "distance_cubic_ft" "mass_cubic_ft"
## [7] "volume_milliliter" "distance_milliliter" "mass_milliliter" "volume_mile" "distance_mile" "mass_mile"
## [13] "volume_kilogram" "distance_kilogram" "mass_kilogram" "volume_pound" "distance_pound" "mass_pound"
Как я мог получить вектор только с комбинациями TRUE
?
Вот вариант с base R
, где используйте apply
с MARGIN = 1
, чтобы перебрать строки, получить names
столбцов со значениями TRUE и paste
с первым столбцом или значением первого элемента
c( apply(df_of_measures, 1, function(x)
paste(x[1], names(x)[-1][as.logical(x[-1])], sep = "_")))
-выход
#[1] "volume_cubic_ft" "volume_milliliter" "distance_meter"
#[4] "distance_mile" "mass_kilogram" "mass_pound"
Или с помощью tidyverse
измените форму на «длинный» формат с помощью pivot_longer
, filter
на основе значений «значение» TRUE и unite
столбцов measure
и name
library(dplyr)
library(tidyr)
df_of_measures %>%
pivot_longer(cols = -measure) %>%
filter(value) %>%
unite(measure, measure, name, sep = "_") %>%
pull(measure)
#[1] "volume_cubic_ft" "volume_milliliter" "distance_meter"
#[4] "distance_mile" "mass_kilogram" "mass_pound"
@MarcosPérez apply
преобразуется в matrix
, и у него может быть только один класс. Таким образом, логическое преобразуется в строку. вот почему я использовал as.logical
Преобразование широкого в длинное с помощью reshape2::melt
,
r <- reshape2::melt(df_of_measures, "measure", names(df_of_measures)[-1])
Reduce(paste0, c(r[r$value, 1:2], "_")[c(1, 3, 2)])
# [1] "distance_meter" "volume_cubic_ft"
# [3] "volume_milliliter" "distance_mile"
# [5] "mass_kilogram" "mass_pound"
или база reshape
.
r <- reshape(as.data.frame(df_of_measures), idvar = "measure",
times=names(df_of_measures)[-1], varying=2:7, v.names = "x", direction = "long")
Reduce(paste0, c(r[r$x, 1:2], "_")[c(1, 3, 2)])
# [1] "distance_meter" "volume_cubic_ft"
# [3] "volume_milliliter" "distance_mile"
# [5] "mass_kilogram" "mass_pound"
Мне нравится ваше первое решение. Можно лучше
function(x) paste(x[1], names(x)[x==TRUE], sep = "_")
.