将值分配给数字因子水平[重复]

Posted

技术标签:

【中文标题】将值分配给数字因子水平[重复]【英文标题】:Assining values to numeric factor levels [duplicate] 【发布时间】:2015-07-19 15:41:02 【问题描述】:

我已经浏览过不同的链接,例如:How to convert a factor to an integer\numeric without a loss of information?

但无法解决问题

我有一个数据框

 SYMBOL             PVALUE1             PVALUE2
1   10-Mar   0.813027629406118    0.78820189558684
2   10-Sep 0.00167287722066533 0.00167287722066533
3   11-Mar    0.21179810441316   0.464576340307205
4   11-Sep 0.00221961024320294 0.00221961024320294
5   12-Sep   0.934667427815304   0.986884425214009
6   15-Sep 0.00167287722066533 0.00167287722066533
7    1-Dec   0.464576340307205  0.0911572830792113
8    1-Mar 0.00818426308604705  0.0252302356363697
9    1-Sep    0.60516237199519   0.570568468332992
10   2-Mar  0.0103975819620539 0.00382292568622066
11   2-Sep 0.00167287722066533 0.00167287722066533

当我尝试str()

str(df)
'data.frame':   20305 obs. of  3 variables:
 $ SYMBOL : Factor w/ 21050 levels "","10-Mar","10-Sep",..: 2 3 4 5 6 7 8 9 10 11 ...
 $ PVALUE1: Factor w/ 209 levels "0","0.000109570493049298",..: 169 22 110 24 181 22 139 39 149 44 ...
 $ PVALUE2: Factor w/ 216 levels "0","0.000109570493049298",..: 172 20 141 23 201 20 90 61 150 29 ...

我试试mode()

sapply(df,mode)
SYMBOL   PVALUE1   PVALUE2 
"numeric" "numeric" "numeric" 

当我尝试根据以下条件为两个数字列(2,3)分配值时,

df$Score <- rowSums(ifelse(df[,-1]==0, 0, 
                                       ifelse(df[, -1]<= 0.05, 2, ifelse(df[,-1]>= 0.065,-2,1))))

I get Warning messages:
1: In Ops.factor(left, right) : ‘<=’ not meaningful for factors
2: In Ops.factor(left, right) : ‘<=’ not meaningful for factors
3: In Ops.factor(left, right) : ‘>=’ not meaningful for factors
4: In Ops.factor(left, right) : ‘>=’ not meaningful for factors

输出如下:

SYMBOL             PVALUE1             PVALUE2       Score
1 10-Mar   0.813027629406118    0.78820189558684         NA
2 10-Sep 0.00167287722066533 0.00167287722066533         NA
3 11-Mar    0.21179810441316   0.464576340307205         NA
4 11-Sep 0.00221961024320294 0.00221961024320294         NA
5 12-Sep   0.934667427815304   0.986884425214009         NA
6 15-Sep 0.00167287722066533 0.00167287722066533         NA

如果因子已经是数字,为什么上面的代码不起作用并给出NA。我应该如何进行。

编辑 dput()

structure(list(SYMBOL = structure(1:6, .Label = c("10-Mar", "10-Sep", 
"11-Mar", "11-Sep", "12-Sep", "15-Sep"), class = "factor"), PVALUE1 = structure(c(4L, 
1L, 3L, 2L, 5L, 1L), .Label = c("0.00167287722066533", "0.00221961024320294", 
"0.21179810441316", "0.813027629406118", "0.934667427815304"), class = "factor"), 
    PVALUE2 = structure(c(4L, 1L, 3L, 2L, 5L, 1L), .Label = c("0.00167287722066533", 
    "0.00221961024320294", "0.464576340307205", "0.78820189558684", 
    "0.986884425214009"), class = "factor")), .Names = c("SYMBOL", 
"PVALUE1", "PVALUE2"), row.names = c(NA, 6L), class = "data.frame")

我也试过这个:

  indx <- sapply(df, is.factor)
    df[indx] <- lapply(df[indx], function(x) as.numeric(levels(x))[x])

    indx returns 

    SYMBOL PVALUE1 PVALUE2 
       TRUE    TRUE    TRUE 
Warning message:
In FUN(X[[3L]], ...) : NAs introduced by coercion

【问题讨论】:

我试过 as.numeric(as.character()) 警告信息:NAs 由强制引入 [1] NA NA NA @ForrestR.Stevens 您建议转换两列,如PVALUE1 PVALUE2 1 169 172 2 22 20 3 110 141 4 24 23 5 181 201 6 22 20 @Gregor 不知道我是否错过了你的观点。 dput(head(df)) 也显示很多数据 @Gregor 请在此处查看文件dropbox.com/s/swv5dej7u45wde9/df.csv?dl=0 我用read.csv读取了你的csv,所有默认选项,我得到SYMBOL作为因子,PVALUE1PVALUE2作为数字。 【参考方案1】:

使用您的 dput 数据,这工作得很好:

df = structure(list(SYMBOL = structure(1:6, .Label = c("10-Mar", "10-Sep", 
"11-Mar", "11-Sep", "12-Sep", "15-Sep"), class = "factor"), PVALUE1 = structure(c(4L, 
1L, 3L, 2L, 5L, 1L), .Label = c("0.00167287722066533", "0.00221961024320294", 
"0.21179810441316", "0.813027629406118", "0.934667427815304"), class = "factor"), 
    PVALUE2 = structure(c(4L, 1L, 3L, 2L, 5L, 1L), .Label = c("0.00167287722066533", 
    "0.00221961024320294", "0.464576340307205", "0.78820189558684", 
    "0.986884425214009"), class = "factor")), .Names = c("SYMBOL", 
"PVALUE1", "PVALUE2"), row.names = c(NA, 6L), class = "data.frame")

df$PVALUE1 = as.numeric(as.character(df$PVALUE1))
df$PVALUE2 = as.numeric(as.character(df$PVALUE2))

df
#   SYMBOL     PVALUE1     PVALUE2
# 1 10-Mar 0.813027629 0.788201896
# 2 10-Sep 0.001672877 0.001672877
# 3 11-Mar 0.211798104 0.464576340
# 4 11-Sep 0.002219610 0.002219610
# 5 12-Sep 0.934667428 0.986884425
# 6 15-Sep 0.001672877 0.001672877

sapply(df, class)
#    SYMBOL   PVALUE1   PVALUE2 
#  "factor" "numeric" "numeric" 

如果您对整个数据框执行此操作时遇到问题,则可能存在一些不规则行。不过,我也查看了您在 cmets 中提供的 CSV,看起来还不错。

另请注意,这是您链接的重复问题中的几个等效解决方案之一。

要转换除第一列之外的所有列,您可以这样做

df[, 2:ncol(df)] = lapply(df[, -1], function(x) as.numeric(as.character(x)))

请注意,您希望以这种方式转换日期列或符号列,因为它们不是数字。

同样,要将命名为 PVALUE1 的列转换为 PVALUE47,您可以构造列名,然后对其进行转换:

col_to_convert = paste0("PVALUE", 1:47)
df[, col_to_convert] = lapply(df[, col_to_convert], function(x) as.numeric(as.character(x)))

一般来说,最佳做法是一开始就不将这些列作为因素。但是,您将这些数据输入 R 可能有一种方法来指定列类,例如,colClasses in read.table、read.csv 等。

【讨论】:

谢谢,但如果我有 200 个这样的列(PVALUE1,2,3,...),应该怎么做 非常感谢您的耐心等待 :)【参考方案2】:

使用data.table的选项

 library(data.table)
 setDT(df)[, 2:3 := lapply(.SD, function(x)
                    as.numeric(levels(x))[x]), .SDcols=2:3]

或者更快一点的版本是使用set

 indx <- which(sapply(df, is.factor) & grepl('PVALUE', names(df)))
 setDT(df)

 for(j in indx)
   set(df, i=NULL, j=j, value= as.numeric(levels(df[[j]]))[df[[j]]])
 

我猜您收到警告的原因是因为您创建的“索引”还包括第一列(因为它也是一个因素),但它不是数字的。通过将非数字元素从 factor 转换为 numeric,这些元素将被强制为 NA。

根据?factor

将因子“f”转换为近似于它的 原始数值,推荐使用“as.numeric(levels(f))[f]” 并且比‘as.numeric(as.character(f))’更高效。

【讨论】:

感谢您的解释。如何为除 first 之外的所有列设置它。我认为这不是正确的方法setDT(df)[, -1 := lapply(.SD, function(x) as.numeric(levels(x))[x]), .SDcols= -1] 你可以使用2:ncol(df) :=.SDcols= 2:ncol(df) 您的这两种方法都可以很好地将因子更改为数字,但是当我尝试此代码df$Score &lt;- rowSums(ifelse(df[,-1]==0, 0, ifelse(df[, -1]&lt;= 0.05, 2, ifelse(df[,-1]&gt;= 0.065,-2,1)))) 进一步为数字列的每个条目分配分数时(首先离开),它会给出错误: Error in rowSums(ifelse(df[, -1] == 0, 0, ifelse(df[, -1] &lt;= : 'x' must be an array of at least two dimensions 请将其作为一个新问题发布,并附上一些示例和预期数据

以上是关于将值分配给数字因子水平[重复]的主要内容,如果未能解决你的问题,请参考以下文章

逐行读取文件,将值分配给变量[重复]

使用列表理解将值分配给字典键[重复]

增强的 for 循环不适用于将值分配给数组(Java)[重复]

是否有内置的方法来模拟将值分配给参数? [重复]

R中的鬼因子水平[重复]

R randomForest子集无法摆脱因子水平[重复]