Специальная форма в R

#r #tidyverse

Вопрос:

Рассмотрим char фрейм данных 3×3:

 example lt;- data.frame(one = c("a","b","c"),  two = c("a","b","b"),  three = c ("c","a","b"))  

Я хочу изменить размер этих данных до 6×2 и добавить следующий контент:

 desired lt;- data.frame(one = c("a","a","b","b",  "c","b"),  two = c("a","c","b","a","b","b"))   

Для исходного кадра данных примера я хочу rbind() просмотреть содержимое примера [,2:3] под каждым индексом строки.

Этого можно достичь путем:

 ex lt;- as.matrix(example)  des lt;- as.data.frame(rbind(ex[,1:2], ex[,2:3]))   

Может library(tidyverse) быть, было бы лучше использовать произвольное количество столбцов?

Ответ №1:

Для каждой пары столбцов транспонируйте определенный ими фрейм субданных и принудительно преобразуйте его в вектор. Затем принудительно введите data.frame и задайте имена результатов.
Приведенный ниже код должен быть масштабируемым, он не жестко определяет количество столбцов.

 desired2 lt;- as.data.frame(  lapply(seq(names(example))[-1], (k) c(t(example[(k-1):k]))) ) names(desired2) lt;- names(example)[-ncol(example)]  identical(desired, desired2) #[1] TRUE  

Приведенный выше код переписан как функция.

 reformat lt;- function(x){  y lt;- as.data.frame(  lapply(seq(names(x))[-1], (k) c(t(x[(k-1):k])))  )  names(y) lt;- names(x)[-ncol(x)]  y }  reformat(example) example %gt;% reformat()  

Другой пример, с вводом 6 столбцов.

 ex1 lt;- example ex2 lt;- example names(ex2) lt;- c("fourth", "fifth", "sixth") ex lt;- cbind(ex1, ex2)  reformat(ex) ex %gt;% reformat()  

Комментарии:

1. Это чистый метод, но я получаю ошибку при определении функции: «неожиданно «)» в «)». Мне интересно, имеет ли это какое-то отношение к этому /(k) ?

2. @M1996rg Может быть, так оно и есть. (k) это новая лямбда, введенная в R4.1.0. Попробуйте function(k) . Время обновить R?

Ответ №2:

tidyverse Подход, использующий tidyr::pivot_longer может выглядеть так:

 library(dplyr) library(tidyr)  pivot_longer(example, -one, values_to = "two") %gt;%   select(-name) #gt; # A tibble: 6 × 2 #gt; one two  #gt; lt;chrgt; lt;chrgt; #gt; 1 a a  #gt; 2 a c  #gt; 3 b b  #gt; 4 b a  #gt; 5 c b  #gt; 6 c b  

Ответ №3:

Решение base-R с Map :

 #iterate over example$one, example$two, and example$three at the same #time, creating the output you need. mylist lt;- Map(function(x ,y ,z ) {  data.frame(one = c(x, y), two = c(y, z)) }, example$one #x, example$two #y, example$three #z)   do.call(rbind, mylist)  one two a.1 a a a.2 a c b.1 b b b.2 b a c.1 c b c.2 b b