我正在尝试制作一个自定义的R脚本来帮助我清理数据,然后再对它做一些有趣的事情。我当前数据集中的很多列都有yes / no值,我认为如果我将它们设为二进制1/0值会更容易查看。这个当前集合有10列可以做到这一点,而这样做十次确实有效:
sd$PhoneService<-ifelse(sd$PhoneService=='Yes', 1,0)
它不容易重复。这对于这个特定项目是可行的,但是如果你有一个需要转换100列的数据集,必须有一种方法。我不能只看它所拥有的级别数,因为有其他列有两个级别,没有多少意义上是二进制。所以我需要一种方法让R遍历表,找到只有两个级别的列,检查这两个级别是“是”和“否”,然后将它们转换为1和0。
这就是我的尝试:
#Get source data
sd = read.csv("source/xyz.csv", header = T, stringsAsFactors=T)
#Clean up data
twoLevelClean <- function(b){
lvlsNames = levels(b)
ifelse(lvlsNames == "Yes", print(lvlsNames), print("Not yes no"))
}
cleanData <- function(a){
lvls = nlevels(a)
ifelse(lvls == 2, sapply(a, twoLevelClean), print("Not 2"))
}
sapply(sd, cleanData)
这只是开始吐出这样的随机输出:
...
[1] "No" "Yes"
[1] "Not yes no"
[1] "No" "Yes"
[1] "Not yes no"
[1] "No" "Yes"
[1] "Not yes no"
[1] "No" "Yes"
[1] "Not yes no"
...
我认为它的第一列有1000多个唯一值,但有超过2个级别。我也不确定我是否正确地走这条路。我应该先看看关卡吗?我希望twoLevelClean函数只在触发它的列上运行,但我不认为这种情况正在发生。我认为它是从一开始就开始的。
for声明会更好吗?我可以索引列并在某些列上运行某些函数吗?
答案 0 :(得分:1)
在原始数据集上使用tidyverse
包,您可以运行以下代码:
Original_data_frame <- data.frame(
c(1:10),
c(rep("Yes",5),rep("No",5)),
c(rep("Yes",5),rep("No",5))
)
names(Original_data_frame ) <- c("id","Var1","Var2")
使用mutate_at
包的dplyr
函数:
Original_data_frame_mod <- Original_data_frame %>%
mutate_at(.vars = vars(Var1,Var2), .funs = funs(ifelse(.=="Yes",1,0)))
答案 1 :(得分:0)
以下是如何做到的:
yn_to_10 = function(x) {
if (! is.factor(x)) return(x)
if (! identical(levels(x), c("no", "yes")) return(x)
return(ifelse(x == "yes", 1, 0))
}
your_data[] = lapply(your_data, yn_to_10)
但是您应该听取注释 - 因子在内部存储为整数(从1开始,而不是0),因此将两级因子更改为二进制0/1并不会真正发生很大变化。