我有一个从Web导入的dataframe(df)。我对df的以下列(名称)感兴趣。 colname的元素被识别为“因素”。来自df的示例如下所示,其中还包含“NA”:
colname
57 +0.10
55
NA
57,5 +2.00
56,5 +0.50
56,5
58
我想用“+”分隔列名,并获得3个数字列,如下所示。
所需的输出是:
colname1 colname2 total
57.00 0.10 57.10
55.00 0.00 55.00
NA NA NA
57.50 2.00 59.50
56.50 0.50 57.00
56.50 0.00 56.50
58.00 0.00 58.00
这也是一个数据框,并且所有的列都是数字。但是,我一直困扰着这个问题。无论我做什么,都无法获得理想的结果。该错误主要是由“NA”和“factor”数据类型引起的。非常感谢您的帮助。
最佳答案
我将使用sub
替换“,”为'。(。read.table/read.csv
也具有dec
选项)。使用cSplit
中的splitstackshape
,通过将sep指定为,
将列分成两部分。输出将为data.table
。创建“总计”通过使用rowSums
列。如果要为所有NA
的行返回NAs
,则可以(在第二个解决方案中显示一个选项)
df$colname <- sub(',', '.', df$colname)
library(splitstackshape)
dt <- cSplit(df, 'colname', '+')
dt[, Total:=rowSums(.SD,na.rm=TRUE)][]
或使用
base R
,使用strsplit
拆分列(“colname”)。输出将是一个“列表”。将“character”转换为“numeric”,填充NAs
以在所有列表元素和rbind
(df2 <- do.call(...,)
)中获得相同的长度。通过rowSums
创建“总计”列,将两列中均为NA
的元素更改为NAs
。 lst <- lapply(strsplit(df$colname, '[+]'), as.numeric)
df2 <- do.call(rbind.data.frame,
lapply(lst, `length<-`, max(sapply(lst, length))))
names(df2) <- paste0('colname', 1:2)
df2$Total <- (NA^!rowSums(!is.na(df2)))*rowSums(df2, na.rm=TRUE)
df2
# colname1 colname2 Total
#1 57.0 0.1 57.1
#2 55.0 NA 55.0
#3 NA NA NA
#4 57.5 2.0 59.5
#5 56.5 0.5 57.0
#6 56.5 NA 56.5
#7 58.0 NA 58.0
或者在这种情况下,也可以使用
eval(parse(
,这将避免将0
更改为NA
的步骤 df2$Total <- unname(sapply(df$colname,
function(x) eval(parse(text=x))))
更新
如果需要将“colname2”中的
NA
替换为0
df2$colname2[with(df2, is.na(colname2) & !is.na(colname1))] <- 0
df2
# colname1 colname2 Total
#1 57.0 0.1 57.1
#2 55.0 0.0 55.0
#3 NA NA NA
#4 57.5 2.0 59.5
#5 56.5 0.5 57.0
#6 56.5 0.0 56.5
#7 58.0 0.0 58.0
数据
df <- structure(list(colname = structure(c(4L, 1L, NA, 5L, 3L, 2L,
6L), .Label = c("55", "56,5", "56,5 +0.50", "57 +0.10", "57,5 +2.00",
"58"), class = "factor")), .Names = "colname", row.names = c(NA,
-7L), class = "data.frame")
关于R用NA分解因子的数据框,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28249490/