将字符的数据帧转换为 R 中具有二进制变量的"more clear"数据帧



从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

我试过:

  1. 将df的所有元素转换为具有唯一元素的字符串向量
  2. 以步骤1(的名称构建df1的结构
  3. 试着用一个循环填充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" 

最新更新