[英]convert similarly named unequally length list elements to data frame R
我知道 dataframe 問題有很多列表,但我找不到這個簡單問題的解決方案。 可以說我有:
library(tidyverse)
library(janitor)
df <- data.frame( group = c(rep("A",3), rep("B", 6)),
test_value = c(0,1,2, 0,1,2,3,4,5))
df_list <- df %>%
split(.$group) %>%
map(~tabyl(.x$test_value))
df_list
# $A
# .x$test_value n percent
# 0 1 0.3333333
# 1 1 0.3333333
# 2 1 0.3333333
# $B
# .x$test_value n percent
# 0 1 0.1666667
# 1 1 0.1666667
# 2 1 0.1666667
# 3 1 0.1666667
# 4 1 0.1666667
# 5 1 0.1666667
我要做的就是將其轉換為以下名為 dataframe 的:
A_test_value A_n A_percent B_test_value B_n B_percent
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0 1 0.333 0 1 0.167
2 1 1 0.333 1 1 0.167
3 2 1 0.333 2 1 0.167
4 NA NA NA 3 1 0.167
5 NA NA NA 4 1 0.167
6 NA NA NA 5 1 0.167
我見過這個,但它略有不同( 將嵌套列表(不等長度)轉換為數據框)
請問有人有一個快速的解決方案(也許dplyr
類型)嗎?
也許你想加入?
library(dplyr)
library(purrr)
library(janitor)
df %>%
group_split(group) %>%
map(~tabyl(.x, test_value)) %>%
reduce(full_join, by = "test_value")
test_value n.x percent.x n.y percent.y
1 0 1 0.3333333 1 0.1666667
2 1 1 0.3333333 1 0.1666667
3 2 1 0.3333333 1 0.1666667
4 3 NA NA 1 0.1666667
5 4 NA NA 1 0.1666667
6 5 NA NA 1 0.1666667
對於命名為 output 的指示組,您可以執行以下操作:
df %>%
split(.$group) %>%
map(~tabyl(.x, test_value)) %>%
imap(~set_names(.x, ifelse(names(.x) != "test_value", paste(.y, names(.x), sep = "_"), names(.x)))) %>%
reduce(full_join, by = "test_value")
test_value A_n A_percent B_n B_percent
1 0 1 0.3333333 1 0.1666667
2 1 1 0.3333333 1 0.1666667
3 2 1 0.3333333 1 0.1666667
4 3 NA NA 1 0.1666667
5 4 NA NA 1 0.1666667
6 5 NA NA 1 0.1666667
您可以首先根據主列表中的子列表names
添加列后綴,然后添加第二個同名的值列的副本,例如"by"
以稍后merge
(也稱為連接)。
df_list <- Map(function(x) {
out <- `names<-`(
df_list[[x]], paste0(x, "_", c("test_value", "n", "percent")))
out <- cbind(out, by=out[,1])
}, names(df_list))
res <- merge(df_list$A, df_list$B, all=TRUE)[, -1]
res
# A_test_value A_n A_percent B_test_value B_n B_percent
# 1 0 1 0.3333333 0 1 0.1666667
# 2 1 1 0.3333333 1 1 0.1666667
# 3 2 1 0.3333333 2 1 0.1666667
# 4 NA NA NA 3 1 0.1666667
# 5 NA NA NA 4 1 0.1666667
# 6 NA NA NA 5 1 0.1666667
基礎 R 解決方案:
# Create the data:
df <- data.frame(group = c(rep("A",3), rep("B", 6)),
test_value = c(0,1,2, 0,1,2,3,4,5))
# Create the dataframe list, splitting on group:
df_list <- lapply(split(df, df$group), data.frame)
# Create the extra vars:
df_list <- mapply(cbind, df_list, "n" = 1, "percent" = 1/sapply(df_list, nrow), SIMPLIFY = FALSE)
# Row bind the dataframe list together into a single dataframe:
df2 <- data.frame(do.call(rbind, df_list), row.names = NULL, stringsAsFactors = FALSE)
# Spread by the test_value:
df2 <- reshape(df2, idvar = 'test_value', ids = unique(df2$test_value), direction = 'wide', timevar = 'group')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.