Итерация с переменными с несколькими временными измерениями: функции purrr и map()

#r #tidyverse #purrr

Вопрос:

У меня есть большая база данных, с которой мне приходится сталкиваться с этой структурой.Структура моей реальной базы данных выглядит так: tibble [561 x 128] (S3: tbl_df/tbl/data. frame)

Давайте обобщим в этом фрейме данных, что мне нужно сделать

 paciente <- c(6430, 6494, 6165, 6278, 6188, 6447, 6207, 6463)
sexo_s1 <-  c("Hombre", "Mujer", "Mujer", "Mujer", "Hombre", "Hombre", "Mujer")
edad_s1 <- c(54, 68, 75, 85, 78, 80, 78, 90)
peso1_v00 <- c(115.2, 85, 98, 87, 85, 78, 84, 98)
cintura1_v00 <- c(115, 125, 110, 114, 120, 121 125, 110)
coltot_v00 <- c(215, 220, 210, 225, 215, 220, 230, 220)
peso1_v66 <- c(110.2, 80, 95, 87, 83, 78, 84, 98)
cintura1_v01 <- c(112, 125, 110, 110, 112, 121 120, 110)
coltot_v01 <- c(210, 210, 205, 215, 215, 210, 230,1 220)
peso1_v01 <- c(110.2, 80, 95, 87, 83, 78, 84, 98)
cintura1_v01 <- c(112, 125, 110, 110, 112, 121 120, 110)
coltot_v01 <- c(210, 210, 205, 215, 215, 210, 230,1 220)
 

Мне нужно выполнить несколько статистических анализов:

Выполните тест на нормальность (shapiro.test и boxplot) для числовых переменных (125 из 128 переменных). Я пытаюсь сделать это с помощью purrr::карта и тому подобное (purrr:map_dfr)

 iterative_example<-map_dfr(.x = quos(paciente, sexo_s1, edad_s1, peso1_v00, cintura1_v00, coltot_v00, peso1_v66, cintura1_v66, coltot_v66, peso1_v01, cintura1_v01, coltot_v01), .f = ~ shapiro.test, data = df_example)
 

ошибка/rlang_error>
Аргумент 1 должен быть фреймом данных или именованным атомарным вектором.
Обратный путь:

муррр::map_dfr(…) dplyr::bind_rows(res, .id = .id)т. Если я обменяюсь map_dfr с картой, я получу список, который я не могу экспортировать или преобразовать в данные.фрейм

 iterative_example<-map(.x = quos(paciente, sexo_s1, edad_s1, peso1_v00, cintura1_v00, coltot_v00, peso1_v66, cintura1_v66, coltot_v66, peso1_v01, cintura1_v01, coltot_v01), .f = ~ shapiro.test, data = df_example)
 

Список из 9:

функция(x)

функция(x)

функция(x)

Я пока не могу экспортировать или отменить список, чтобы получить результаты p-значения и t, но я разберусь с этим. Однако я хотел бы получить фрейм данных.

Аналогично этой операции я должен выполнить итеративный t.тест между переменными, наблюдаемыми в разное время, если есть существенная разница между выполненными измерениями (я пробовал ту же функцию отображения, но получаю точный вложенный список, например, с помощью shapiro.test

 t.test(df_example$peso1_v00,  df_example$peso1_v66)
t.test(df_example$cintura1_v00,  df_example$cintura1_v66)
 

Синтаксис для распознавания имени переменной:
«i_variable1_v00» в определенное время «v00» и тестирование с помощью «i_variable1_v66». Я пробовал: starts_with (), но безрезультатно

Я не уверен, как это сделать и экспортировать выходные данные

T-тест Уэлча с двумя образцами

данные: df_выборка$cintura1_v00 и df_выборка$cintura1_v66 t = -0,051503, df = 10,399, p-значение = 0,9599 альтернативная гипотеза: истинная разница в средних не равна 0 95-процентный доверительный интервал: -5,504848 5,254848 выборочные оценки: среднее значение x среднее значение y 117,500 117,625

2 — Создайте новые столбцы из значений 0, 6 и 12 месяцев подряд. Я создал переменные, но системно повторяю строки с переменными в базе данных. Пример с переменной differente в моей базе данных.

Я ищу sthg для создания переменных в новых столбцах итеративно между переменными, взятыми в разные моменты времени:

d_peso1_v66: разница 0- 6 месяцев d_peso1_v01: разница 0 — 12 месяцев

Пример с 2 переменными без итерации:

 df_example<-mutate(df_example, d_peso1_v66 = peso1_v66 - peso1_v00)
df_example<-mutate(df_example, d_coltot_v01 = coltot_v01 - coltot_v00)
 

d_variable1_v66 = i_variable1_v66 — i_variable1_v00
d_variable1_v01 = i_variable1_v01 — i_variable1_v00

d_variable2_v01 = i_variable2_v66 — i_variable2_v00 d_variable2_v01 = i_variable2_v01 — i_variable2_v00

 df_example <-mutate(across(where(is.numeric)),
varname <- paste("varname01", if variable contains "01" )
df_example <- mutate(df, varname = Petal.Width * n)
 

Не уверен, можно ли выполнить это за один шаг, или необходимо создать функцию и пройти через базу данных с функцией карты. Sthg, как это, но делает разницу (функция difference_function)

 meanofcol <- function(df, col) {
mutate(df, "Mean of {{col}}" := mean({{col}}))
}
meanofcol(iris, Petal.Width)`
 

А затем с функцией карты

 df_example2 <- map_dfr (.x = df_example, .f = ~ difference_function, data = df_example)
 

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

Ответ №1:

Попробуй это. Обратите внимание, что я удалил дубликаты строк в ваших данных.

 df <- data.frame(
  paciente = c(6430, 6494, 6165, 6278, 6188, 6447, 6207, 6463),
  sexo_s1 =  c("Hombre", "Mujer", "Mujer", "Mujer", "Hombre", "Hombre", "Mujer", "Hombre"),
  edad_s1 = c(54, 68, 75, 85, 78, 80, 78, 90),
  peso1_v00 = c(115.2, 85, 98, 87, 85, 78, 84, 98),
  cintura1_v00 = c(115, 125, 110, 114, 120, 121, 125, 110),
  coltot_v00 = c(215, 220, 210, 225, 215, 220, 230, 220),
  peso1_v66 = c(110.2, 80, 95, 87, 83, 78, 84, 98),
  cintura1_v01 = c(112, 125, 110, 110, 112, 121, 120, 110),
  peso1_v01 = c(110.2, 80, 95, 87, 83, 78, 84, 98),
  coltot_v01 = c(210, 210, 205, 215, 215, 210, 230, 220))

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)
library(broom)

## First you need to convert non-numeric variables recorded as number into factor

df$paciente <- factor(df$paciente)

## Select numeric variables, pivot in long format, analyse

df |> 
  select(where(is.numeric)) |> 
  pivot_longer(everything()) |>
  group_by(name) |> 
  do(tidy(shapiro.test(.$value)))
#> # A tibble: 8 × 4
#> # Groups:   name [8]
#>   name         statistic p.value method                     
#>   <chr>            <dbl>   <dbl> <chr>                      
#> 1 cintura1_v00     0.897  0.270  Shapiro-Wilk normality test
#> 2 cintura1_v01     0.806  0.0330 Shapiro-Wilk normality test
#> 3 coltot_v00       0.958  0.792  Shapiro-Wilk normality test
#> 4 coltot_v01       0.896  0.269  Shapiro-Wilk normality test
#> 5 edad_s1          0.925  0.469  Shapiro-Wilk normality test
#> 6 peso1_v00        0.870  0.149  Shapiro-Wilk normality test
#> 7 peso1_v01        0.905  0.322  Shapiro-Wilk normality test
#> 8 peso1_v66        0.905  0.322  Shapiro-Wilk normality test

## Now select only *_v00 and *_v66, then pivot to longer and separate

df |> 
  select(paciente, matches("_v00|_v01|_v66")) |> 
  pivot_longer(-paciente) |> 
  separate(name, into=c("name", "time"), sep="_") |> 
  pivot_wider(names_from=time, values_from=value) |> 
  group_by(name) |> 
  do(tidy(t.test(.$v00, .$v01)))
#> # A tibble: 3 × 11
#> # Groups:   name [3]
#>   name     estimate estimate1 estimate2 statistic p.value parameter conf.low
#>   <chr>       <dbl>     <dbl>     <dbl>     <dbl>   <dbl>     <dbl>    <dbl>
#> 1 cintura1     2.5      118.      115       0.824   0.424      14.0    -4.01
#> 2 coltot       5        219.      214.      1.42    0.178      13.4    -2.58
#> 3 peso1        1.88      91.3      89.4     0.329   0.747      13.9   -10.4 
#> # … with 3 more variables: conf.high <dbl>, method <chr>, alternative <chr>
 

Создано 2021-09-16 пакетом reprex (v2.0.1)

Вы можете изменить код, чтобы получить другое сравнение (например, 00 против 66).