Как переместить нижнюю половину значений столбца во вновь созданный столбец?

У меня есть столбец, содержащий средние значения трех разных измерений в первых 50% строк и соответствующие стандартные ошибки в последних 50% строк. В предыдущем столбце указаны имена, используемые для каждого из них (meanNativeSR, meanExoticSR, meanTotalSR, seN, seE, seT). Я хотел создать 2 новых столбца, которые содержат имена se_ в первом столбце и их значения во втором столбце, а затем избавиться от этих нижних 50% строк. Вот мой набор данных:

df <- structure(list(Invasion = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 
3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 
2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 
1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L
), .Label = c("Low", "Medium", "High"), class = "factor"), Growth = structure(c(1L, 
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 
3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 
1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 
2L, 3L, 1L, 2L, 3L), .Label = c("cover", "herb", "woody"), class = "factor"), 
    mean_se = c("meanNativeSR", "meanNativeSR", "meanNativeSR", 
    "meanNativeSR", "meanNativeSR", "meanNativeSR", "meanNativeSR", 
    "meanNativeSR", "meanNativeSR", "meanExoticSR", "meanExoticSR", 
    "meanExoticSR", "meanExoticSR", "meanExoticSR", "meanExoticSR", 
    "meanExoticSR", "meanExoticSR", "meanExoticSR", "meanTotalSR", 
    "meanTotalSR", "meanTotalSR", "meanTotalSR", "meanTotalSR", 
    "meanTotalSR", "meanTotalSR", "meanTotalSR", "meanTotalSR", 
    "seN", "seN", "seN", "seN", "seN", "seN", "seN", "seN", "seN", 
    "seE", "seE", "seE", "seE", "seE", "seE", "seE", "seE", "seE", 
    "seT", "seT", "seT", "seT", "seT", "seT", "seT", "seT", "seT"
    ), value = c(0.769230769230769, 0.230769230769231, 0.923076923076923, 
    2.46153846153846, 6.84615384615385, 0.538461538461538, 1.69230769230769, 
    1.76923076923077, 1.15384615384615, 0.384615384615385, 0, 
    1.38461538461538, 1.76923076923077, 0, 2.23076923076923, 
    2.07692307692308, 0.769230769230769, 2.46153846153846, 1.15384615384615, 
    0.230769230769231, 2.53846153846154, 4.23076923076923, 6.84615384615385, 
    3.23076923076923, 3.76923076923077, 2.76923076923077, 3.84615384615385, 
    0.280883362823162, 0.12162606385263, 0.329364937914491, 0.312463015562922, 
    0.705710715103738, 0.24325212770526, 0.36487819155789, 0.280883362823162, 
    0.191021338791684, 0.140441681411581, 0, 0.180400606147055, 
    0.201081886427668, 0, 0.230769230769231, 0.329364937914491, 
    0.12162606385263, 0.24325212770526, 0.273771237231572, 0.12162606385263, 
    0.24325212770526, 0.394738572265145, 0.705710715103738, 0.440772139427464, 
    0.532938710021193, 0.257050482766198, 0.336767321450351)), row.names = c(NA, 
-54L), class = c("tbl_df", "tbl", "data.frame"))

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

#create an intermediate data.frame that contains just the means and their values from the first half of original df
df.mean <- head(df, -27)
#rename columns 3 and 4
colnames(df.mean)[3] <- "mean"
colnames(df.mean)[4] <- "mean_value"


#create another intermediate data.frame with standard error values from the bottom half of original df
df.se <- df[28:54,]
#rename columns 3 and 4
colnames(df.se)[3] <- "se"
colnames(df.se)[4] <- "se_value"


#cbind those together to get desired result
df.final <- cbind(df.mean, df.se[,3:4])

#remove intermediates
rm(df.mean); rm(df.se)

Есть ли более простой способ сделать это, возможно, используя каналы или некоторые функции в tidyverse, или даже с помощью базы R?

Стоит ли изучать 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
0
422
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вот подход с pivot_wider и unnest:

library(tidyverse)
df %>%
    mutate(class = str_extract(mean_se,"(N|E|T)"),
           fun = str_extract(mean_se,"(mean|se)")) %>%
    pivot_wider(id_cols = c("Invasion","Growth"), names_from = "fun",
                values_from = c("mean_se","value")) %>%
  unnest()
# A tibble: 27 x 6
   Invasion Growth mean_se_mean mean_se_se value_mean value_se
   <fct>    <fct>  <chr>        <chr>           <dbl>    <dbl>
 1 Low      cover  meanNativeSR seN             0.769    0.281
 2 Low      cover  meanExoticSR seE             0.385    0.140
 3 Low      cover  meanTotalSR  seT             1.15     0.274
 4 Low      herb   meanNativeSR seN             0.231    0.122
 5 Low      herb   meanExoticSR seE             0        0    
 6 Low      herb   meanTotalSR  seT             0.231    0.122
 7 Low      woody  meanNativeSR seN             0.923    0.329
 8 Low      woody  meanExoticSR seE             1.38     0.180
 9 Low      woody  meanTotalSR  seT             2.54     0.243
10 Medium   cover  meanNativeSR seN             2.46     0.312
# … with 17 more rows

Вы получите несколько предупреждений, но, тем не менее, это должно сработать.

С tidyverse мы могли бы сделать group_split, изменить имена столбцов и сделать inner_join

library(dplyr)
library(purrr)
df %>%
   group_split(grp = row_number() > 27, .keep = FALSE) %>% 
   map2(list(c('mean', 'mean_value'), c('se', 'se_value')),
        ~ {nm1 <- .y
           .x  %>%
             rename_at(3:4, ~ nm1) %>%
             mutate(rn = row_number())} ) %>% 
  reduce(inner_join) %>% 
  select(-rn)

-выход

# A tibble: 27 x 6
#   Invasion Growth mean         mean_value se    se_value
#   <fct>    <fct>  <chr>             <dbl> <chr>    <dbl>
# 1 Low      cover  meanNativeSR      0.769 seN      0.281
# 2 Low      herb   meanNativeSR      0.231 seN      0.122
# 3 Low      woody  meanNativeSR      0.923 seN      0.329
# 4 Medium   cover  meanNativeSR      2.46  seN      0.312
# 5 Medium   herb   meanNativeSR      6.85  seN      0.706
# 6 Medium   woody  meanNativeSR      0.538 seN      0.243
# 7 High     cover  meanNativeSR      1.69  seN      0.365
# 8 High     herb   meanNativeSR      1.77  seN      0.281
# 9 High     woody  meanNativeSR      1.15  seN      0.191
#10 Low      cover  meanExoticSR      0.385 seE      0.140
# … with 17 more rows
Ответ принят как подходящий

Я думаю, что нет более короткого и простого способа достижения ваших целей, кроме объединения вещей. Самая длинная часть вашего кода — это назначение новых имен столбцов, которые нельзя сократить. Остальное можно поместить в одну строку. Но на самом деле вы всегда должны балансировать между краткостью и удобочитаемостью.

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

df_final_2 <- cbind(head(df, -27), df[28:54,3:4])
colnames(df_final_2)[3:6] <- c("mean", "mean_value","se", "se_value")

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