R: 给 dataframe 的某列赋值、分组、因子化

###################################################

问题:给某一列赋值、分组、分类、因子化   18.4.24

         如何把 data.frame 中的某一列,赋值、即分组分类,,

解决方案:

         先 复制 要赋值的这一列,

         iris1<- iris;  range(iris1$Sepal.Length)    #[1] 4.3  7.9 得到数据范围,为下面分段

         方法一: 常规赋值,,可适用于被赋值列为 numeric、character 均可。为 numeric 时可用< > >= <= 等,character 时可用 == 方式。

iris1$Sepal.Length_fuzhi1 <- iris1$Sepal.Length;

str(iris1)

iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length < 5] <- 1  #条件用 iris1$Sepal.Length 列,而不用新复制的列,是为了防止犯错    

iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length >= 5 & iris1$Sepal.Length < 6] <- 2

iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length >= 6 & iris1$Sepal.Length < 7] <- 3

iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length >= 7] <- 4;

str(iris1)    

  

         方法二: 自动循环赋值,,用于被赋值列可以比较大小,如 numeric 型,

iris1<- iris
num_assign <- function(temp_df,col_name,clas,newname){ ##此函数为通用函数。。对可以比大小的列进行赋值的函数。 # temp_data 即要处理的数据框的名字,col_name为数据框中要处理的列名。 # clas为分组界限组成的向量。。newname为赋值后的新产生的列的列名。、。。。 temp_df[["temp1"]] = temp_df[["temp"]] <- temp_df[[col_name]]; CI <- rep("a",length(clas)+1); #CI 用来显示 原来值与新赋的值 之间对应关系。 for(i in 1:length(clas)) { if(i == 1){ #得到第一个区间 temp_df[["temp"]][temp_df[["temp1"]] < clas[i]] <- i CI[i] <- paste("<",clas[i]) }else if(i>1 & i<length(clas)){ ###得到 第 2 到第 n-1 个区间 temp_df[["temp"]][temp_df[["temp1"]] >= clas[i-1] & temp_df[["temp1"]] < clas[i]] <- i CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i]) }else{ #得到第n个和n+1个区间 temp_df[["temp"]][temp_df[["temp1"]] >= clas[i-1] & temp_df[["temp1"]] < clas[i]] <- i CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i]) temp_df[["temp"]][temp_df[["temp1"]] >= clas[i]] <- i+1 CI[i+1] <- paste0(">=",clas[i]) } } temp_df <- subset(temp_df,select = -temp1) #删除临时列temp1 names(temp_df)[names(temp_df)=="temp"] = newname #将新的列名赋给临时列名。 assign_explain <- data.frame(num = 1:(length(clas)+1),CI = CI); assign_explain result <- list(temp_df=temp_df,assign_explain=assign_explain) return(result) } #应用上面函数: iris1 <- num_assign(iris1,"Sepal.Length",c(5,6,7),"fuzhii_")[[1]] assign_explain_age <- num_assign(iris1,"Sepal.Length",c(5,6,7),"fuzhii_")[[2]]; assign_explain_age

  方法二: 自动循环赋值,,用于被赋值列不能比较大小,如 character 型,

chr_assign <- function(temp_df,col_name,newname){    ##此函数为通用函数。。对不用比大小的列进行赋值的函数。
    # temp_data 即要处理的数据框的名字,col_name为数据框中要处理的列名。
    # 。newname为赋值后的新产生的列的列名。、。。。
    temp_df[["temp1"]] = temp_df[["temp"]] <- as.character(temp_df[[col_name]])
    clas <- as.character(unique(temp_df[["temp1"]]))
    CI <- rep("a",length(clas))    #用来生成原值 和 所赋值的对应关系
    for(i in 1:length(clas)) {
      temp_df[["temp"]][temp_df[["temp1"]] == clas[i]] <- i
      CI[i] <- clas[i]
    }
    temp_df <- subset(temp_df,select = -temp1)   #删除临时列temp1
    names(temp_df)[names(temp_df)=="temp"] = newname   #将新的列名赋给临时列名。
    assign_explain <- data.frame(num = 1:(length(clas)),CI = CI)  #生成赋值与相应区间的对应关系变量
    result <- list(temp_df=temp_df,assign_explain=assign_explain)
    return(result)
}
#应用上面函数:
iris1 <- chr_assign(iris1,"Species","leibie")[[1]]; str(iris1) assign_explain_age <- chr_assign(iris1,"Species","leibie")[[2]]; assign_explain_age

  

讨论扩展:同上的思路,可以扩展用于分类变量,不限于比较大小的 numeric 型。另外亦可将iris1 作为中间数据框,用 iris1 <- new_data.frame .

         扩展1:

        筛选条件 iris1$Sepal.Length < 5 返回一个逻辑向量,长度为 iris1 的长度150,这在将来赋值的时候 iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length < 5] <- 1 ,会不会计算 150 次,是TRUE了,赋值,,是 FALSE 了,不赋值。

        改换条件方式为:which(iris1$Sepal.Length < 5) 返回一个位置向量,长度为满足筛选条件的行数22,这在将来赋值时候,会不会更有效率。。??。。

 扩展2:扩版方法二: 用于 numeric character 型。。

        

         if(num_or_char == "num"){
                   temp_df <- iris1
                   temp_df$temp1 = temp_df$temp <- temp_df$Sepal.Length
                   clas <- c(5,6,7); clas      ### seq(from=, to=, by=)
                   CI <- rep("a",length(clas)+1);    #用来生成赋值后的区间 和 所赋值的对应关系
                   for(i in 1:length(clas)) {
                     if(i == 1){ #得到第一个区间
                            temp_df$temp[temp_df$temp1 < clas[i]] <- i    ### 即满足 <5
                            CI[i] <- paste("<",clas[i])
                     }else if(i>1 & i<length(clas)){    ###得到 第 2 到第 n-1 个区间
                            temp_df$temp[temp_df$temp1 >= clas[i-1] & temp_df$temp1 < clas[i]] <- i    ### 即满足 5 =< x < 6
                            CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i])
                     }else{     #得到第n个和n+1个区间
                            temp_df$temp[temp_df$temp1 >= clas[i-1] & temp_df$temp1 < clas[i]] <- i   ### 即满足 6 =< x < 7
                            CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i])
                            temp_df$temp[temp_df$temp1 >= clas[i]] <- i+1     ### 即满足 x >= 7
                            CI[i+1] <- paste0(">",clas[i])
                     }
                   }
                   temp_df <- subset(temp_df,select = -temp1)   #删除临时列temp1
                   names(temp_df)[names(temp_df)=="temp"] = "newname"
                   assign_explain <- data.frame(num = 1:(length(clas)+1),CI = CI); assign_explain   #生成赋值与相应区间的对应关系变量
         }
         if(num_or_char == "char"){
                   temp_df <- iris1
                   temp_df$temp1 = temp_df$temp <- as.character(temp_df$Species)

###################################################

 

讨论扩展:同上的思路,可以扩展用于分类变量,不限于比较大小的 numeric 型。另外亦可将iris1 作为中间数据框,用 iris1 <- new_data.frame .

         扩展1:

                   筛选条件 iris1$Sepal.Length < 5 返回一个逻辑向量,长度为 iris1 的长度150,这在将来赋值的时候 iris1$Sepal.Length_fuzhi1[iris1$Sepal.Length < 5] <- 1 ,会不会计算 150 次,是TRUE了,赋值,,是 FALSE 了,不赋值。

                   改换条件方式为:which(iris1$Sepal.Length < 5) 返回一个位置向量,长度为满足筛选条件的行数22,这在将来赋值时候,会不会更有效率。。??。。

         扩展2:扩版方法二: 用于 numeric character 型。。

         if(num_or_char == "num"){

                   temp_df <- iris1

                   temp_df$temp1 = temp_df$temp <- temp_df$Sepal.Length

                   clas <- c(5,6,7); clas      ### seq(from=, to=, by=)

                   CI <- rep("a",length(clas)+1);    #用来生成赋值后的区间 和 所赋值的对应关系

                   for(i in 1:length(clas)) {

                     if(i == 1){ #得到第一个区间

                            temp_df$temp[temp_df$temp1 < clas[i]] <- i    ### 即满足 <5

                            CI[i] <- paste("<",clas[i])

                     }else if(i>1 & i<length(clas)){    ###得到 第 2 到第 n-1 个区间

                            temp_df$temp[temp_df$temp1 >= clas[i-1] & temp_df$temp1 < clas[i]] <- i    ### 即满足 5 =< x < 6

                            CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i])

                     }else{     #得到第n个和n+1个区间

                            temp_df$temp[temp_df$temp1 >= clas[i-1] & temp_df$temp1 < clas[i]] <- i   ### 即满足 6 =< x < 7

                            CI[i] <- paste0(clas[i-1],"<=","x","<",clas[i])

                            temp_df$temp[temp_df$temp1 >= clas[i]] <- i+1     ### 即满足 x >= 7

                            CI[i+1] <- paste0(">",clas[i])

                     }

                   }

                   temp_df <- subset(temp_df,select = -temp1)   #删除临时列temp1

                   names(temp_df)[names(temp_df)=="temp"] = "newname"

                   assign_explain <- data.frame(num = 1:(length(clas)+1),CI = CI); assign_explain   #生成赋值与相应区间的对应关系变量

         }

         if(num_or_char == "char"){

                   temp_df <- iris1

                   temp_df$temp1 = temp_df$temp <- as.character(temp_df$Species)

                   clas <- as.character(unique(temp_df$temp));clas

                   CI <- rep("a",length(clas));    #用来生成原值 和 所赋值的对应关系

                   for(i in 1:length(clas)) {

                     temp_df$temp[temp_df$temp1 == clas[i]] <- i

                     CI[i] <- clas[i]

                   }

                   temp_df <- subset(temp_df,select = -temp1)   #删除临时列temp1

                   names(temp_df)[names(temp_df)=="temp"] = "newname"   #将临时列 temp 重命名为设置的列名

                   assign_explain <- data.frame(num = 1:length(clas),CI = CI); assign_explain   #生成赋值与相应区间的对应关系变量

         }

        

另请参阅:for 循环,,自定义函数,,

        clas <- as.character(unique(temp_df$temp));clas

                   CI <- rep("a",length(clas));    #用来生成原值 和 所赋值的对应关系

                   for(i in 1:length(clas)) {

                     temp_df$temp[temp_df$temp1 == clas[i]] <- i

                     CI[i] <- clas[i]

                   }

                   temp_df <- subset(temp_df,select = -temp1)   #删除临时列temp1

                   names(temp_df)[names(temp_df)=="temp"] = "newname"   #将临时列 temp 重命名为设置的列名

                   assign_explain <- data.frame(num = 1:length(clas),CI = CI); assign_explain   #生成赋值与相应区间的对应关系变量

         }

        

另请参阅:for 循环,,自定义函数,,

猜你喜欢

转载自www.cnblogs.com/li-20151130/p/9037864.html