R语言入门求助:如何基于其他列特定字符串值创建新列?
问题描述
作为编程和R语言新手,我需要用R完成硕士研究项目的数据分析,目标是根据数据框中PCLVL和PSLVL两列的字符串值创建新列Perf,但尝试了嵌套for循环和嵌套if语句均未成功,附上尝试的代码、初始数据框及期望结果,寻求解决方法。
尝试的方法
方法1:嵌套for循环
y <- 1 for (i in Scores$PCLVL){ for (j in Scores$PSLVL){ if (i == "High" && j == "High"){ Scores$Perf[y] <- "Mixed Perfectionism" y <- y + 1 } else if (i == "Low" && j == "High"){ Scores$Perf[y] <- "PSP" y <- y + 1 } else if (i == "High" && j == "Low"){ Scores$Perf[y] <- "ECP" y <- y + 1 } else if (i == "Low" && j == "Low"){ Scores$Perf[y] <- "Non Perfectionism" y <- y + 1 } } }
问题:嵌套循环会遍历PCLVL和PSLVL的所有组合(笛卡尔积),导致y的增长远超过数据行数,结果完全错误,且这种场景根本不需要嵌套循环。
方法2:嵌套if语句
Scores$Perf <- if (Scores$PCLVL == "High" & Scores$PSLVL == "High", 'Mixed Perfectionism', if else (Scores$PCLVL == "High" & Scores$PSLVL == "Low", 'ECP', if else (Scores$PCLVL == "Low" & Scores$PSLVL == "High", 'PSP', 'Non Perfectionism' if else (Scores$PCLVL == "Low" & Scores$PSLVL == "Low", 'Non Perfectionism', 'NA'))))
问题:语法错误。R中处理向量的条件函数是ifelse()(连写,无空格),而if只能处理单个逻辑值,不能直接用于向量;同时代码的括号和参数结构混乱,导致无法运行。
初始数据框
Scores <- data.frame( PCLVL = c("High", "High", "Low", "High", "High", "Low"), PSLVL = c("High", "High", "High", "High", "High", "High") )
(注:期望结果中第2、5行的PSLVL值与初始数据不一致,推测是笔误,以下解决方案基于期望结果的逻辑处理)
期望结果
PCLVL PSLVL Perf 1 High High Mixed Perfectionism 2 High Low ECP 3 Low High PSP 4 High High Mixed Perfectionism 5 Low Low Non Perfectionism 6 Low High PSP
解决方案
方法1:嵌套ifelse()(基础R实现,向量化)
R是向量式语言,优先用向量化操作代替循环,ifelse()可直接处理整个向量:
Scores$Perf <- ifelse( Scores$PCLVL == "High" & Scores$PSLVL == "High", "Mixed Perfectionism", ifelse( Scores$PCLVL == "High" & Scores$PSLVL == "Low", "ECP", ifelse( Scores$PCLVL == "Low" & Scores$PSLVL == "High", "PSP", "Non Perfectionism" ) ) )
注意:ifelse是连写的,每个ifelse的参数为(条件, 满足条件的结果, 不满足条件的结果),结构要严谨。
方法2:dplyr::case_when()(更直观易读)
如果使用tidyverse工具链,case_when()的语法更清晰,适合多条件判断:
# 先安装并加载dplyr包(首次使用需安装) # install.packages("dplyr") library(dplyr) Scores <- Scores %>% mutate(Perf = case_when( PCLVL == "High" & PSLVL == "High" ~ "Mixed Perfectionism", PCLVL == "High" & PSLVL == "Low" ~ "ECP", PCLVL == "Low" & PSLVL == "High" ~ "PSP", TRUE ~ "Non Perfectionism" # 所有未匹配的情况默认值 ))
这种方法将条件与结果一一对应,可读性和可维护性远高于嵌套ifelse()。
方法3:修复for循环(仅作逻辑理解,不推荐)
如果一定要用循环,只需逐行遍历即可,无需嵌套:
# 先初始化新列,避免内存反复分配 Scores$Perf <- character(nrow(Scores)) for (row in 1:nrow(Scores)) { pclvl <- Scores$PCLVL[row] pslvl <- Scores$PSLVL[row] if (pclvl == "High" && pslvl == "High") { Scores$Perf[row] <- "Mixed Perfectionism" } else if (pclvl == "Low" && pslvl == "High") { Scores$Perf[row] <- "PSP" } else if (pclvl == "High" && pslvl == "Low") { Scores$Perf[row] <- "ECP" } else if (pclvl == "Low" && pslvl == "Low") { Scores$Perf[row] <- "Non Perfectionism" } }
直接遍历行号,每次取当前行的两个值判断,避免了嵌套循环的笛卡尔积问题。
内容的提问来源于stack exchange,提问作者Zac MacDonald
相关产品推荐
相关产品推荐

