Переместите наблюдение в разные строки - PullRequest
0 голосов
/ 02 августа 2020

например,

У меня есть этот фрейм данных:

a 1 2 3 4 5 6
b 7 8 9 1 2 3
c 4 5 6 7 8 9 

, и я хочу преобразовать его в:

a 1 2 3
a 4 5 6
b 7 8 9
b 1 2 3
c 4 5 6
c 7 8 9

По сути, для каждой отдельной строки я хотите, например, чтобы значения переменных со 2-го по 6-й, с 7-го по 11-й, с 11-го по 15-й ... переместили строку ниже, где первым значением переменной является буква исходной строки.

Что мне делать? Я пытался работать с gather (), но здесь это не так. Я только новичок в R и буду благодарен за любую помощь. спасибо

Ответы [ 4 ]

3 голосов
/ 02 августа 2020

Группирует по 3 столбцам; просто измените %/% 3 на %/% 5 для разного количества столбцов. (Предполагается, что в каждой группе равное количество столбцов.)

out <- do.call(rbind, lapply(split.default(dat[,-1], (seq_along(dat[,-1])-1) %/% 3), 
                             function(a) cbind(dat[,1,drop=FALSE], unname(a))))
out
#     V1 1 2 3
# 0.1  a 1 2 3
# 0.2  b 7 8 9
# 0.3  c 4 5 6
# 1.1  a 4 5 6
# 1.2  b 1 2 3
# 1.3  c 7 8 9

И мы можем немного очистить это с помощью

row.names(out) <- NULL
out[order(out[,1]),]
#   V1 1 2 3
# 1  a 1 2 3
# 4  a 4 5 6
# 2  b 7 8 9
# 5  b 1 2 3
# 3  c 4 5 6
# 6  c 7 8 9
1 голос
/ 03 августа 2020

Вот еще один базовый вариант R

cbind(
  df[rep(1:nrow(df), each = 2), ][1],
  do.call(
    "+",
    lapply(0:1,
      FUN = function(k) {
        kronecker(
          as.matrix(df[-1][(3*k-1)+2:4]),
          (matrix(c(1, 0), nrow = 2) + k) %% 2
        )
      }
    )
  )
)

такой, что

    V1 1 2 3
1    a 1 2 3
1.1  a 4 5 6
2    b 7 8 9
2.1  b 1 2 3
3    c 4 5 6
3.1  c 7 8 9
1 голос
/ 03 августа 2020

Если показанные данные совпадают с показанными, это можно сделать путем простого разделения столбцов и rbind наборов данных после установки одинаковых имен столбцов

library(dplyr)
rbind(df1[1:4], setNames(df1[c(1, 5:7)], names(df1)[1:4])) %>% 
      arrange(1)

Если столбцов много, автоматическим c методом, который легче понять, будет seq. L oop по последовательности индекса, подмножество столбцов, rbind внутри do.call, так как мы создаем list путем цикла

out <- cbind(df1[1], do.call(rbind, lapply(seq(2, ncol(df1), by = 3),
    function(i) setNames(df1[i:(i+2)], paste0("v", 2:4)))))
out[order(out$v1),]

data

df1 <- structure(list(v1 = c("a", "b", "c"), v2 = c(1L, 7L, 4L), v3 = c(2L, 
8L, 5L), v4 = c(3L, 9L, 6L), v5 = c(4L, 1L, 7L), v6 = c(5L, 2L, 
8L), v7 = c(6L, 3L, 9L)), class = "data.frame", row.names = c(NA, 
-3L))
0 голосов
/ 02 августа 2020

С tidyverse

Версия жесткого кода

  1. Изолируйте первые 4 столбца (три значения и ключ), используя select

  2. rbind и select последние 3 столбца и ключ

  3. EDIT Обязательно переименуйте столбцы, которые должны быть объединены с rbind, в то же имя, что и выбор df из шага 1.

  4. arrange с помощью клавиши

      df %>% 
       select(1:4) %>% 
       rbind(df %>% select(1, "v1" = 5,
                              "v2" = 6, 
                              "v3" = 7)) %>%
       arrange(key)
    
    
    
         #    key v1 v2 v3
         # 1   a  1  2  3
         # 2   a  4  5  6
         # 3   b  7  8  9
         # 4   b  1  2  3
         # 5   c  4  5  6
         # 6   c  7  8  9
    

EDIT Generalized (a немного волосатее)

sample df

   set.seed(42)
    df_2 <- tibble(
      bug = letters,
      col1 = sample(1:26),
      col2 = sample(1:26),
      col3 = sample(1:26),
      col4 = sample(1:26),
      col5 = sample(1:26),
      col6 = sample(1:26),
      col7 = sample(1:26),
      col8 = sample(1:26),
      col9 = sample(1:26),
      col10 = sample(1:26),
      col11 = sample(1:26),
      col12 = sample(1:26),
      col13 = sample(1:26),
      col14 = sample(1:26),
      col15 = sample(1:26)
    )

Функция, удовлетворяющая обобщенному подходу

   create_rowgroups.f <- function(df, key, groupsize){
  if( !(key %in% colnames(df)) ){
    print(paste(key, "is expected to be a column in df"))
    stop()
  }
  if( (ncol(df)-1) %% groupsize != 0 ){
    print("Function requires groups to fit all variable columns with the exception of the key")
    stop()
  }
  fnames = colnames(df[ , 1: (groupsize + 1) ])      
  df_2 <- bind_rows(lapply(
    1:(ncol(df)/groupsize),
    function(df, groupsize, key, fnames, index){
      pos1 = (index * groupsize) - groupsize + 2
      pos2 = (index * groupsize) + 1
      tempdf <- df %>% select(!!key, !!pos1:!!pos2)
      colnames(tempdf) = fnames
      return(tempdf)
    },
    df = df,
    key = key,
    fnames = fnames,
    groupsize = groupsize
  ))
  df_2 <- df_2 %>% arrange(across(.cols = key))
  return(df_2)
}

Это большой объем кода, который обтекает простую строку lapply для помощи OP в использовании UDF, create_rowgroups.f

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...