如何创建组成员的 table 或数据框(按组的项目,来自长格式数据)?
How can I create a table or data frame of members of a group (items by group, from long format data)?
我正在处理一些聚类分析结果。我正在尝试为我正在进行的每个集群分析创建集群成员表。
例如:
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=F))
head(test_data)
Cluster Item
1 2 R
2 5 F
3 1 T
4 5 Q
5 3 B
6 3 J
我想制作这样的东西:
Cluster_1 Cluster_2 Cluster_3 Cluster_4 Cluster_5
T R C P L
K O J M Q
I H B N F
D G E
S A
我第一次尝试 spread
,但没有使用这些数据
spread(test_data, item,group)
错误:行的标识符重复
spread(test_data, group,item)
错误:行的标识符重复
然后我尝试了:
test_frame <- split.data.frame(test_data,test_data$group)
但这会产生一个数据框列表,每个组都有一个数据框。我一直无法成功地将其操纵成我想要的。
我尝试了unnest
和unlist
,但是因为每个组都有不同数量的成员元素,所以这些函数会出错。
引入 NA 就好了。
是否有一种我忽略的直接方法来完成此操作?
修改了我的答案。全部在 base R 中。相当简洁:
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T), stringsAsFactors=FALSE)
clusters <- unique(test_data$Cluster)
test_data <- lapply(clusters, function(i) {
test_data[test_data$Cluster == i,]$Item } )
n_max <- Reduce(f=max, x=lapply(test_data, FUN=length))
test_data <- lapply(test_data, function(i) {length(i) <- n_max; i})
test_data <- Reduce(x=test_data, f=cbind)
test_data <- as.data.frame(test_data)
names(test_data) <- paste0('Cluster_', clusters)
test_data
这是一个使用 tidyverse
的解决方案。 test_final
是最终输出。
# Load package
library(tidyverse)
# Set seed for reproducibility
set.seed(123)
# Create example data frame
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T))
# Split the data frame into a list of data frames
test_list <- test_data %>%
mutate(Item = as.character(Item)) %>%
arrange(Cluster) %>%
split(f = .$Cluster)
# Find out the maximum row number of each data frame
max_row <- max(map_int(test_list, nrow))
# Design a function to process each data frame in test_list
process_fun <- function(dt, max_row){
# Append NA to the Item column
dt_vec <- dt$Item
dt_vec2 <- c(dt_vec, rep(NA, max_row - nrow(dt)))
# Get the cluster number
clusterNum <- unique(dt$Cluster)
# Create a new data frame
dt2 <- data_frame(Item = dt_vec2)
# Change column name
colnames(dt2) <- paste("Cluster", clusterNum, sep = "_")
return(dt2)
}
# Process the data
test_final <- test_list %>%
map(process_fun, max_row = max_row) %>%
bind_cols()
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T),stringsAsFactors = FALSE)
m <- with(test_data,tapply(Item,paste("Cluster",Cluster,sep="_"),I))
e <- data.frame(sapply(m,`length<-`,max(lengths(m))))
print(e,na.print="")
我正在处理一些聚类分析结果。我正在尝试为我正在进行的每个集群分析创建集群成员表。
例如:
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=F))
head(test_data)
Cluster Item
1 2 R
2 5 F
3 1 T
4 5 Q
5 3 B
6 3 J
我想制作这样的东西:
Cluster_1 Cluster_2 Cluster_3 Cluster_4 Cluster_5
T R C P L
K O J M Q
I H B N F
D G E
S A
我第一次尝试 spread
,但没有使用这些数据
spread(test_data, item,group)
错误:行的标识符重复
spread(test_data, group,item)
错误:行的标识符重复
然后我尝试了:
test_frame <- split.data.frame(test_data,test_data$group)
但这会产生一个数据框列表,每个组都有一个数据框。我一直无法成功地将其操纵成我想要的。
我尝试了unnest
和unlist
,但是因为每个组都有不同数量的成员元素,所以这些函数会出错。
引入 NA 就好了。
是否有一种我忽略的直接方法来完成此操作?
修改了我的答案。全部在 base R 中。相当简洁:
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T), stringsAsFactors=FALSE)
clusters <- unique(test_data$Cluster)
test_data <- lapply(clusters, function(i) {
test_data[test_data$Cluster == i,]$Item } )
n_max <- Reduce(f=max, x=lapply(test_data, FUN=length))
test_data <- lapply(test_data, function(i) {length(i) <- n_max; i})
test_data <- Reduce(x=test_data, f=cbind)
test_data <- as.data.frame(test_data)
names(test_data) <- paste0('Cluster_', clusters)
test_data
这是一个使用 tidyverse
的解决方案。 test_final
是最终输出。
# Load package
library(tidyverse)
# Set seed for reproducibility
set.seed(123)
# Create example data frame
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T))
# Split the data frame into a list of data frames
test_list <- test_data %>%
mutate(Item = as.character(Item)) %>%
arrange(Cluster) %>%
split(f = .$Cluster)
# Find out the maximum row number of each data frame
max_row <- max(map_int(test_list, nrow))
# Design a function to process each data frame in test_list
process_fun <- function(dt, max_row){
# Append NA to the Item column
dt_vec <- dt$Item
dt_vec2 <- c(dt_vec, rep(NA, max_row - nrow(dt)))
# Get the cluster number
clusterNum <- unique(dt$Cluster)
# Create a new data frame
dt2 <- data_frame(Item = dt_vec2)
# Change column name
colnames(dt2) <- paste("Cluster", clusterNum, sep = "_")
return(dt2)
}
# Process the data
test_final <- test_list %>%
map(process_fun, max_row = max_row) %>%
bind_cols()
test_data <- data.frame(
Cluster = sample(1:5,100,replace=T),
Item = sample(LETTERS[1:20],5, replace=T),stringsAsFactors = FALSE)
m <- with(test_data,tapply(Item,paste("Cluster",Cluster,sep="_"),I))
e <- data.frame(sapply(m,`length<-`,max(lengths(m))))
print(e,na.print="")