从R中的数据帧开始,如下所示(df(:
year_1 <- c('James','Mike','Jane', NA)
year_2 <- c('Evelyn', 'Jackson', 'James', 'Avery')
year_3 <- c('Harper', 'Avery', NA, NA)
df <- data.frame(year_1, year_2, year_3)
我想把它转换成类似df1的东西(当然,我的原始数据帧中有数百个元素,所以我不能手动进行(
names <- c('James','Mike','Jane','Evelyn', 'Jackson', 'Avery', 'Harper')
year_1 <- c('YES','YES','YES', 'NO', 'NO', 'NO', 'NO')
year_2 <- c('YES','NO','NO', 'YES', 'YES', 'YES', 'NO')
year_3 <- c('NO','NO','NO', 'NO', 'NO', 'YES', 'YES')
df_1 <- data.frame(year_1, year_2, year_3)
rownames(df_1) <- names
我试过:
- 将df的所有元素转换为具有唯一元素的字符串向量
- 以步骤1(的名称构建df1的结构
- 试着用一个循环填充df1(这里是我无法构建正确循环的地方(
知道吗?
谢谢!!
使用stack
+table
的基本R选项
> as.data.frame(ifelse(table(stack(df)) == 1, "YES", "NO"))
year_1 year_2 year_3
Avery NO YES YES
Evelyn NO YES NO
Harper NO NO YES
Jackson NO YES NO
James YES YES NO
Jane YES NO NO
Mike YES NO NO
这里有一个tidyverse
选项,我们将数据重塑为"长"格式pivot_longer
,获得distinct
行,创建一列"YES",并使用pivot_wider
将其重塑为"宽">
library(dplyr)
library(tidyr)
library(tibble)
df %>%
pivot_longer(cols = everything(), values_drop_na = TRUE) %>%
distinct %>%
mutate(new = 'YES') %>%
pivot_wider(names_from = name, values_from = new, values_fill = 'NO') %>%
column_to_rownames("value")
-输出
# year_1 year_2 year_3
#James YES YES NO
#Evelyn NO YES NO
#Harper NO NO YES
#Mike YES NO NO
#Jackson NO YES NO
#Avery NO YES YES
#Jane YES NO NO
这个怎么样?
sapply(df, function(x) sapply(na.omit(unique(unlist(df))), `%in%`, x))
# year_1 year_2 year_3
# James TRUE TRUE FALSE
# Mike TRUE FALSE FALSE
# Jane TRUE FALSE FALSE
# Evelyn FALSE TRUE FALSE
# Jackson FALSE TRUE FALSE
# Avery FALSE TRUE TRUE
# Harper FALSE FALSE TRUE
要提供另一个选项,首先我们可以使用嵌套的for循环从df中提取唯一的名称。我们测试该名称是否已经在我们的列表中,并进一步测试我们是否正在查看NA。
people<-c()
for (i in 1:length(colnames(df))){
for (j in 1:length(df[,1])){
pers<-df[j,i]
if (!(pers %in% people)){
if (!is.na(pers)){
people<-c(people,toString(pers))
}
}
}
}
从这里开始,我们可以每年迭代一次简单的%in%检查,并组合成一个完整的数据帧。上面的答案可能更简单,但我发现,如果您需要在数据通过脚本时对其进行其他小的更改,那么像这样的代码非常有用。
for (i in 1:length(colnames(df))){
colname<-colnames(df)[i]
peoplein<-people %in% df[,i]
if (i == 1){
df1<-cbind(people,peoplein)
colnames(df1)[i+1]<-colname
} else {
df1<-cbind(df1,peoplein)
colnames(df1)[i+1]<-colname
}
}
得到的df1如下所示。
people year_1 year_2 year_3
[1,] "James" "TRUE" "TRUE" "FALSE"
[2,] "Mike" "TRUE" "FALSE" "FALSE"
[3,] "Jane" "TRUE" "FALSE" "FALSE"
[4,] "Evelyn" "FALSE" "TRUE" "FALSE"
[5,] "Jackson" "FALSE" "TRUE" "FALSE"
[6,] "Avery" "FALSE" "TRUE" "TRUE"
[7,] "Harper" "FALSE" "FALSE" "TRUE"