繁体   English   中英

R 旋转到宽和回到长(多组)

[英]R pivot to wide and back to long (multiple groups)

我一直在使用宽表格式来创建迁移变量(年份、市政 -> 年份、市政、移动),并且想知道是否可以将其翻转回长表格式。 但是,我现在每年有 2 个小组而不是一个小组。 我查看了 SO 上的现有帖子,但找不到任何类似的内容。

这是我所做的:

library(tidyverse)
library(rlang)

# sample data
mydata <- data.frame(id = sort(rep(1:10,3)),
                     year = rep(seq(2009,2011),10),
                     municip = sample(c(NA,1:3),30,replace=TRUE))

数据如下所示:

ID 市政厅
1 2009年 2
1 2010年 1
1 2011年 3
2 2009年 1
2 2010年 1
2 2011年 3
3 2009年 不适用
3 2010年 不适用
3 2011年 不适用
# turn sideways
mydata.wide <- mydata %>%
  pivot_wider(names_from = year,
              names_prefix = "municip.",
              values_from = municip)

现在它看起来像这样:

ID municip.2009 municip.2010 municip.2011
1 2 1 3
2 1 1 3
3 不适用 不适用 不适用
4 1 不适用 3
5 1 不适用 2
6 3 2 2
7 2 不适用 3
8 3 不适用 3
9 不适用 1 不适用
10 1 不适用 2

然后我添加了一个迁移变量(实际上这已经完成了 12 年):

# create migration variable
for (i in 2009:2010){
  
  text.string <- paste0("mydata.wide <- mydata.wide %>%
          mutate(move.",i+1," = case_when(
            is.na(municip.",i,") & is.na(municip.",i+1,") ~ \"NA\",
            is.na(municip.",i,") & !is.na(municip.",i+1,") ~ \"1\",
            !is.na(municip.",i,") & !is.na(municip.",i+1,") 
               & municip.",i," != municip.",i+1," ~ \"3\",
            !is.na(municip.",i,") & is.na(municip.",i+1,") ~ \"4\",   
            TRUE ~ \"2\"
          ))")
  
  eval(parse_expr(text.string))                        
}

# NA: missing in both cases
# 1: move into region
# 2: stayed in region
# 3: moved within region
# 4: moved out of region

现在该表如下所示:

ID municip.2009 municip.2010 municip.2011 move.2010 move.2011
1 2 1 3 3 3
2 1 1 3 2 3
3 不适用 不适用 不适用 不适用 不适用
4 1 不适用 3 4 1
5 1 不适用 2 4 1
6 3 2 2 3 2
7 2 不适用 3 4 1
8 3 不适用 3 4 1
9 不适用 1 不适用 1 4
10 1 不适用 2 4 1

我想要做的是将其翻转回来以创建如下内容:

ID 市政厅 移动
1 2009年 2 不适用
1 2010年 1 3
1 2011年 3 3
2 2009年 1 不适用
2 2010年 1 2
2 2011年 3 3
3 2009年 不适用 不适用
3 2010年 不适用 不适用
3 2011年 不适用 不适用

我不确定这是否可以单独使用pivot_longer来完成。 我尝试了几种变体。 有任何想法吗?

你可以试试这个:

df <- tribble(~id, ~municip.2009, ~municip.2010, ~municip.2011, ~move.2010, ~move.2011,
1,  2,  1,  3,  3,  3,
2,  1,  1,  3,  2,  3,
3,  NA, NA, NA, NA, NA,
4,  1,  NA, 3,  4,  1,
5,  1,  NA, 2,  4,  1,
6,  3,  2,  2,  3,  2,
7,  2,  NA, 3,  4,  1,
8,  3,  NA, 3,  4,  1,
9,  NA, 1,  NA, 1,  4,
10, 1,  NA, 2,  4,  1
)


df %>%
  pivot_longer(cols = -1, names_to = "temp1", values_to = "count") %>% 
  separate(col = temp1, c("temp2", "year")) %>% 
  pivot_wider(names_from = temp2, values_from = count)

pivot_longer收集municip并在同一列中move separate分裂municipmoveyears ; 最后使用pivot_wider获得最终结果。

不要横向思考,要长远考虑!

现在,我不能完全回答你的问题,因为我真的不明白你在计算什么。 它是某种因素(1-4)吗? 但我相信你可以自己完成。 考虑以下:

> mydata %>% group_by(id) %>% 
  arrange(year) %>% 
  mutate(last_year = lag(municip)) %>% 
  ungroup %>% 
  arrange(id) %>% as.data.frame # ignore this line, it is simply for the pleasure of seeing the data.frame
   id year municip last_year
1   1 2009       3        NA
2   1 2010       2         3
3   1 2011      NA         2
4   2 2009      NA        NA
5   2 2010      NA        NA
6   2 2011       1        NA
7   3 2009       3        NA
8   3 2010       2         3
9   3 2011       2         2
10  4 2009       2        NA
11  4 2010      NA         2
12  4 2011       1        NA
13  5 2009       3        NA
14  5 2010      NA         3
15  5 2011       2        NA
16  6 2009       1        NA
17  6 2010       3         1
18  6 2011       2         3
19  7 2009       3        NA
20  7 2010       2         3
21  7 2011       2         2
22  8 2009      NA        NA
23  8 2010      NA        NA
24  8 2011       3        NA
25  9 2009       1        NA
26  9 2010      NA         1
27  9 2011       1        NA
28 10 2009       3        NA
29 10 2010      NA         3
30 10 2011      NA        NA

你看? 在长格式中,您现在可以简单地继续

%>% mutate(move = case_when(
  is.na(.$municip) & is.na(.$last_year) ~ \"NA\",
  # etc.
  ))

你想要从第一年到下一年的比较吗? 使用函数lead而不是lag

最后,您的文本代码可能不起作用; 使用case_when您必须使用.$引用管道结果中的变量。

像这样的东西?

mydata.wide %>% 
  pivot_longer(
    cols = -id,
    names_pattern = "([a-z]+?)\\.(\\d+)", 
    names_to = c("name", "year"),
    values_to = "val",
    values_transform = list(val = as.character)
    ) %>% 
  pivot_wider(
    names_from = name,
    values_from = val
  ) %>% 
  print(n=30)
 A tibble: 30 × 4
      id year  municip move 
   <int> <chr> <chr>   <chr>
 1     1 2009  2       NA   
 2     1 2010  3       3    
 3     1 2011  NA      4    
 4     2 2009  2       NA   
 5     2 2010  NA      4    
 6     2 2011  2       1    
 7     3 2009  1       NA   
 8     3 2010  2       3    
 9     3 2011  1       3    
10     4 2009  NA      NA   
11     4 2010  NA      NA   
12     4 2011  1       1    
13     5 2009  NA      NA   
14     5 2010  2       1    
15     5 2011  3       3    
16     6 2009  3       NA   
17     6 2010  3       2    
18     6 2011  3       2    
19     7 2009  NA      NA   
20     7 2010  NA      NA   
21     7 2011  NA      NA   
22     8 2009  NA      NA   
23     8 2010  2       1    
24     8 2011  NA      4    
25     9 2009  3       NA   
26     9 2010  2       3    
27     9 2011  NA      4    
28    10 2009  2       NA   
29    10 2010  3       3    
30    10 2011  1       3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM