dplyr 在变量的子集上使用pivot_longer和pivot_wider

hmh*_*sen 4 r dplyr

有没有办法在变量的子集上使用pivot_longerand ?pivot_wider这是一个例子。首先,我将创建一个具有所需起始结构的数据框。

library(tidyverse)

# Assume this as starting df
arrests <- USArrests %>% 
  as_tibble(rownames = "State") %>% 
  pivot_longer(-State, names_to = "Crime", values_to = "Value") %>% 
  group_by(State) %>% 
  mutate(Total = sum(Value)) %>% 
  ungroup()

arrests
# A tibble: 200 x 4
   State   Crime    Value Total
   <chr>   <chr>    <dbl> <dbl>
 1 Alabama Murder    13.2  328.
 2 Alabama Assault  236    328.
 3 Alabama UrbanPop  58    328.
 4 Alabama Rape      21.2  328.
 5 Alaska  Murder    10    366.
 6 Alaska  Assault  263    366.
 7 Alaska  UrbanPop  48    366.
 8 Alaska  Rape      44.5  366.
 9 Arizona Murder     8.1  413.
10 Arizona Assault  294    413.
# ... with 190 more rows
Run Code Online (Sandbox Code Playgroud)

所以我们正在使用arrest数据框。现在我想将“总计”折叠到“犯罪”中,以便“总计”是犯罪中的一个值,就像“谋杀”一样。

我也想做相反的事情。将“Total”折叠到“Crime”后,我想pivot_wider在“Crime”上使用,但仅在 的值上使用Crime == "Total"。

这些行动可能吗?

akr*_*run 5

一种选择是add_row。完成按“州”分割的组后,循环遍历list并map添加具有“总计”列的第一个值的行(add_row来自tibble)并删除“总计”列

\n\n
library(dplyr)\nlibrary(purrr)\nlibrary(tibble)\narrests2 <- arrests %>%\n         group_split(State) %>%\n         map_dfr(~ .x %>% \n               add_row(State = .$State[1], Crime = 'Total',\n                        Value = .$Total[1]) %>%\n                select(-Total))\narrests2\n# A tibble: 250 x 3\n#  State   Crime    Value\n# * <chr>   <chr>    <dbl>\n# 1 Alabama Murder    13.2\n# 2 Alabama Assault  236  \n# 3 Alabama UrbanPop  58  \n# 4 Alabama Rape      21.2\n# 5 Alabama Total    328. \n# 6 Alaska  Murder    10  \n# 7 Alaska  Assault  263  \n# 8 Alaska  UrbanPop  48  \n# 9 Alaska  Rape      44.5\n#10 Alaska  Total    366. \n# \xe2\x80\xa6 with 240 more rows\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者另一种选择是summarise使用“总计”值,然后执行bind_rows

\n\n
arrests %>% \n   group_by(State) %>% \n   summarise(Crime = 'Total', Value = first(Total)) %>% \n   bind_rows(arrests %>% select(-Total), .)  %>% \n   arrange(State)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

或者使用pivot_longer

\n\n
library(tidyr)\narrests %>%\n    pivot_longer(cols = Value:Total) %>% \n    mutate(Crime = replace(Crime, name == 'Total', 'Total')) %>% \n    select(-name) %>%\n    distinct()\n# A tibble: 250 x 3\n#   State   Crime    value\n#   <chr>   <chr>    <dbl>\n# 1 Alabama Murder    13.2\n# 2 Alabama Total    328. \n# 3 Alabama Assault  236  \n# 4 Alabama UrbanPop  58  \n# 5 Alabama Rape      21.2\n# 6 Alaska  Murder    10  \n# 7 Alaska  Total    366. \n# 8 Alaska  Assault  263  \n# 9 Alaska  UrbanPop  48  \n#10 Alaska  Rape      44.5\n# \xe2\x80\xa6 with 240 more rows\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

如果我们需要执行相反的操作,则按“州”分组,通过提取与“犯罪”相对应的“值”作为“总计”来创建“总计”列,并filter取出犯罪为“总计”的行

\n\n
arrests2 %>%\n    group_by(State) %>% \n    mutate(Total = Value[Crime == 'Total'])  %>%\n    filter(Crime != 'Total')\n# A tibble: 200 x 4\n# Groups:   State [50]\n#   State   Crime    Value Total\n#   <chr>   <chr>    <dbl> <dbl>\n# 1 Alabama Murder    13.2  328.\n# 2 Alabama Assault  236    328.\n# 3 Alabama UrbanPop  58    328.\n# 4 Alabama Rape      21.2  328.\n# 5 Alaska  Murder    10    366.\n# 6 Alaska  Assault  263    366.\n# 7 Alaska  UrbanPop  48    366.\n# 8 Alaska  Rape      44.5  366.\n# 9 Arizona Murder     8.1  413.\n#10 Arizona Assault  294    413.\n# \xe2\x80\xa6 with 190 more rows\n
Run Code Online (Sandbox Code Playgroud)\n