Abr*_*efa 3 pivot-table r dplyr
我正在处理一些政府来源的数据,其格式可以使用此代码复制:
Names <- c(rep("A",5),rep("B",5), rep("C",5))
Types <- c(rep(c("Income","Tax Paid","Consumption","Stimulus","NonDurable expenses"),3))
year1 <- c(rep(c(1000,100,300,100,200),3))
year2 <- c(rep(c(2000,200,600,200,400),3))
year3 <- c(rep(c(4000,400,800,400,800),3))
df <- data.frame(Names,Types,year1,year2,year3)
Run Code Online (Sandbox Code Playgroud)
我想要的是一个新的数据框
| 姓名 | 年 | 收入 | 税 | 消耗 | 刺激 | 非耐用型 |
|---|---|---|---|---|---|---|
| A | 第一年 | 1000 | 100 | 300 | 100 | 200 |
| A | 第二年 | 1000 | 100 | 300 | 100 | 200 |
| A | 第三年 | 1000 | 100 | 300 | 100 | 200 |
| 乙 | 第一年 | 2000年 | 200 | 600 | 200 | 400 |
| 乙 | 第二年 | 2000年 | 200 | 600 | 200 | 400 |
| 乙 | 第三年 | 2000年 | 200 | 600 | 200 | 400 |
就这样继续下去。因此,对于每个人来说,将表格放在很长的位置year,并使用单元格名称作为Types具有相应值的新列。
我想到了一种处理这个问题的方法:按类型过滤掉每个类型,然后为每种类型设置单独的数据帧pivot_longer,然后是bind_cols结果。但我认为这是低效的。这是我的代码:
df %>% filter(Types == "Income") %>%
pivot_longer(cols=c(year1:year3), names_to = "Year", values_to = "income") %>% select(-Types) %>%
bind_cols(df %>% filter(Types == "Tax Paid") %>%
pivot_longer(cols=c(year1:year3), names_to = "Year", values_to = "Tax_paid") %>% select(Tax_paid)) %>%
bind_cols(df %>% filter(Types == "Consumption") %>%
pivot_longer(cols=c(year1:year3), names_to = "Year", values_to = "Consumption") %>% select(Consumption)) %>%
bind_cols(df %>% filter(Types == "Stimulus") %>%
pivot_longer(cols=c(year1:year3), names_to = "Year", values_to = "Stimulus") %>% select(Stimulus)) %>%
bind_cols(df %>% filter(Types == "NonDurable expenses") %>%
pivot_longer(cols=c(year1:year3), names_to = "Year", values_to = "NonDurable_expenses") %>% select(NonDurable_expenses))
Run Code Online (Sandbox Code Playgroud)
有人可以帮助编写更好、更高效的代码吗?
我认为这符合你的要求
library(tidyr); library(dplyr)
(df
|> pivot_longer(year1:year3, names_to = "year")
|> pivot_wider(names_from = Types)
|> rename_with(~ stringr::str_remove(., " +.*"))
)
Run Code Online (Sandbox Code Playgroud)
(整个表达式周围的额外括号是我的一种奇怪的格式/风格偏好;这样做允许每行以管道开头,而不是必须确保它们以管道结尾......)