首页 > 解决方案 > 使用for循环检查列是否存在并创建一个新列

问题描述

这是我的df(我的完整数据集最多20个列项,为简单起见,只显示前3个,即INC_D.1、INC_D.2、INC_D.3):

Item <- c("A","B","C")
INC_D.1 <- c("10A345","255789","402B56")
CODE_D.1 <- c("2","4","5")
INC_D.2 <- c("675C98","404D34","203559")
CODE_D.2 <- c("5","3","2")
INC_D.3 <- c("LG99w0e03","1025gg205","w2krt2")
CODE_D.3 <- c("3","2","2")
df <- as.data.frame(cbind(Item,INC_D.1,CODE_D.1,INC_D.2,CODE_D.2,INC_D.3,CODE_D.3))

最初我使用以下代码来检查列是否存在并一一创建新变量:

if("CODE_D.1" %in% colnames(df))
{df$INC_D.1 <- as.character(df$INC_D.1)
df$INC_D.1.2only <- as.character(ifelse(df$CODE_D.1=="2",df$INC_D.1,""))}

if("CODE_D.2" %in% colnames(df))
{df$INC_D.2 <- as.character(df$INC_D.2)
df$INC_D.2.2only <- as.character(ifelse(df$CODE_D.2=="2",df$INC_D.2,""))}

if("CODE_D.3" %in% colnames(df))
{df$INC_D.3 <- as.character(df$INC_D.3)
df$INC_D.3.2only <- as.character(ifelse(df$CODE_D.3=="2",df$INC_D.3,""))}

我正在尝试使用 forloop 重写代码:

for (i in 1:3){
    if(paste0("CODE_D.",i) %in% colnames(df)){
        for (j in 1:nrow(df)){
            if(df[paste0("CODE_D.",i)][j,]=="2"){
                print(paste0("True:[INC=",i,",ROW=",j,"]"))         #Check        
                df[paste0("INC_D.",i,".2only")] <- c(rep("",nrow(df)))
                df[paste0("INC_D.",i,".2only")][j,] <- as.character(df[paste0("INC_D.",i)][j,])
            }
        }
    }
}

for 循环可以运行,但缺少 INC_D.3.2only 的元素之一,这是输出:

[1] "True:[INC=1,ROW=1]"
[1] "True:[INC=2,ROW=3]"
[1] "True:[INC=3,ROW=2]"
[1] "True:[INC=3,ROW=3]"
> df
  Item INC_D.1 CODE_D.1 INC_D.2 CODE_D.2   INC_D.3 CODE_D.3 INC_D.1.2only INC_D.2.2only INC_D.3.2only
1    A  10A345        2  675C98        5 LG99w0e03        3        10A345                            
2    B  255789        4  404D34        3 1025gg205        2                                          
3    C  402B56        5  203559        2    w2krt2        2                      203559        w2krt2

如何修改以获得所需的输出

标签: r

解决方案


通过base R的一个想法是根据列名进行拆分,根据您的条件替换值并绑定,即

cbind.data.frame(df, do.call(cbind, 
        lapply(split.default(df[-1], gsub('.*_', '', names(df[-1]))), function(i)
               {i <- replace(i[1], i[2] != 2, ''); 
                names(i) <- paste0(names(i), 'only'); 
                i})))

这使,

  Item INC_D.1 CODE_D.1 INC_D.2 CODE_D.2   INC_D.3 CODE_D.3 INC_D.1only INC_D.2only INC_D.3only
1    A  10A345        2  675C98        5 LG99w0e03        3      10A345        <NA>        <NA>
2    B  255789        4  404D34        3 1025gg205        2        <NA>        <NA>   1025gg205
3    C  402B56        5  203559        2    w2krt2        2        <NA>      203559      w2krt2

推荐阅读