#r
#r
Вопрос:
Это данные, которые у меня есть:
id<-c(1:7)
emp1<-c('ft','ft','pt','pt','ft','no','no')
emp2<-c('ft','ft','ft','ft','no','pt','ft')
marstat1<-c('married','married','divorced','single','single','single','single')
marstat2<-c('divorced','married','divorced','single','single','married','single')
df<-data.frame(id,emp1,emp2,marstat1,marstat2)
Я хочу изменить (от широкого до длинного) его в
id<-c(1,1,2,2,3,3,4,4,5,5,6,6,7,7)
year<-c(rep(1:2,7))
emp<-c('ft','ft','ft','ft','pt','ft','pt','ft','ft','no','no','pt','no','ft')
marstat<-c('married','divorced','married','married','divorced','divorced','single','single','single','single','single','married','single','single')
df2<-data.frame(id,year,emp,marstat)
Я пытался использовать dplyr::gather, но он дает мне 4 строки каждого идентификатора вместо 2. И мне непонятно, что делать с измерением года (мне не нужны два столбца года, только один)
df2<-df %>%
gather(key='year',value='emp',emp1,emp2) %>%
gather(key='year2',value='marstat',marstat1,marstat2)
Ответ №1:
Рассмотрим этот подход
df %>%
pivot_longer(matches("\d$"), names_to = c("name", "year"), names_pattern = "([^\d] )(\d )$") %>%
pivot_wider()
Сначала преобразуйте фрейм данных в один, содержащий только три столбца id
, nameyear
, и value
; одновременно разделите второй столбец nameyear
на name
и year
. Затем просто поверните два столбца name
и value
шире.
Вывод
# A tibble: 14 x 4
id year emp marstat
<int> <chr> <chr> <chr>
1 1 1 ft married
2 1 2 ft divorced
3 2 1 ft married
4 2 2 ft married
5 3 1 pt divorced
6 3 2 ft divorced
7 4 1 pt single
8 4 2 ft single
9 5 1 ft single
10 5 2 no single
11 6 1 no single
12 6 2 pt married
13 7 1 no single
14 7 2 ft single
Комментарии:
1. Красиво! Я собираюсь записать это. Очень полезно! Спасибо!
2. Спасибо. Это сработало! Я не понимаю эти части: «\ d $», «([^ \ d] ) (\ d ) $») … но я предполагаю, что это базовая грамматика R для поиска числовых или символьных строк?
3. Нет, это регулярные выражения. Смотрите Это для получения дополнительной информации. @kna123
Ответ №2:
Может быть, это может быть полезно для вас:
library(tidyverse)
#Code
newdf <- df %>% select(c('id',starts_with('emp'))) %>%
pivot_longer(-id) %>%
mutate(name=gsub('emp','',name)) %>%
rename(emp=value,year=name) %>%
left_join(
df %>% select(c('id',starts_with('marstat'))) %>%
pivot_longer(-id) %>%
mutate(name=gsub('marstat','',name)) %>%
rename(marstat=value,year=name)
)
Вывод:
# A tibble: 14 x 4
id year emp marstat
<int> <chr> <fct> <fct>
1 1 1 ft married
2 1 2 ft divorced
3 2 1 ft married
4 2 2 ft married
5 3 1 pt divorced
6 3 2 ft divorced
7 4 1 pt single
8 4 2 ft single
9 5 1 ft single
10 5 2 no single
11 6 1 no single
12 6 2 pt married
13 7 1 no single
14 7 2 ft single
Ответ №3:
Не самое элегантное решение, но это сработало бы:
pivot_longer(df, cols=starts_with("marstat"), names_to="year", names_prefix="marstat", values_to="marstat") %>%
pivot_longer(cols=starts_with("emp"), names_to="empyear", names_prefix="emp", values_to="emp") %>%
filter(year==empyear) %>%
select(-empyear)
Это приводит к двум последовательным сводкам, за которыми следует удаление строк, в которых номер года не совпадает, и, наконец, удаление лишнего столбца year. Обратите внимание, что «names_prefix» позволяет удалить текстовую часть marstat1 / 2 и emp1 / 2, но в итоге вы все равно получите chr
вектор, который вам нужно будет преобразовать в целое число, если вам это нужно.
Дать вам это:
A tibble: 14 x 4
id year marstat emp
<int> <chr> <fct> <fct>
1 1 1 married ft
2 1 2 divorced ft
3 2 1 married ft
4 2 2 married ft
5 3 1 divorced pt
6 3 2 divorced ft
7 4 1 single pt
8 4 2 single ft
9 5 1 single ft
10 5 2 single no
11 6 1 single no
12 6 2 married pt
13 7 1 single no
14 7 2 single ft