我有从web导入的数据帧(df)。我对df的以下列(colname)感兴趣。 colname的元素被识别为"因素"。来自df的样本如下所示,其中还包括" NA" s:
colname
57 +0.10
55
NA
57,5 +2.00
56,5 +0.50
56,5
58
我想通过" +"分拆colname。并获得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"和#34;因素"数据类型。我会很高兴得到任何帮助非常感谢。
答案 0 :(得分:6)
我会使用sub
将“,”替换为“。”。(read.table/read.csv
也有dec
选项。)使用cSplit
中的splitstackshape
,将sep指定为,
,将列拆分为两个。输出为data.table
。使用rowSums
创建“总计”列。如果要返回{{1对于所有NA
的行,它是可能的(第二个解决方案中显示了一个选项)
NAs
或使用df$colname <- sub(',', '.', df$colname)
library(splitstackshape)
dt <- cSplit(df, 'colname', '+')
dt[, Total:=rowSums(.SD,na.rm=TRUE)][]
,使用base R
拆分列(“colname”)。输出将是“列表”。将“字符”转换为“数字”,填充strsplit
以使所有列表元素和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
答案 1 :(得分:5)
这是另一个想法。您可以退后一步,并使用read.table()
的许多参数。在这里我们可以使用sep = "+"
,因为该函数将剥离列之间的空格。
df <- read.table(text = x, col.names = c("V1", "V2"),
colClasses = c(V1 = "numeric", V2 = "character"),
dec = ",", skip = 1, fill = TRUE, sep = "+"
)
因此V2
将成为删除了+
个符号的字符列。因此,还有一些步骤可以使列成为数字并排列NA。为此,我们可以使用
within(df, {
V2 <- replace(type.convert(V2), !nzchar(V2), 0)
is.na(V2) <- is.na(V1)
V3 <- V1 + V2
})
# V1 V2 V3
# 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
其中x
是
"colname\n57 +0.10\n55\nNA\n57,5 +2.00\n56,5 +0.50\n56,5\n58"
更新/改进:您也可以使用fread()
和1.9.5中提供的新tstrsplit()
功能执行此操作。这也允许您从文件中读取表而不先创建data.frame。
library(data.table)
fread(x, sep = "\n")[,
tstrsplit(colname, "\\s?[+]", fill="0")][,
lapply(.SD, function(x) type.convert(chartr(",", ".", x), as.is=TRUE))
][, V3 := rowSums(.SD)][]
# V1 V2 V3
# 1: 57.0 0.1 57.1
# 2: 55.0 0.0 55.0
# 3: NA 0.0 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
答案 2 :(得分:4)
使用dplyr
和tidyr
:
library(tidyr)
library(dplyr)
df %>%
separate(colname, c("colname1", "colname2"), extra = "drop", convert = TRUE, '[+]') %>%
mutate(colname1 = as.numeric(gsub(",", ".", colname1)),
colname2 = ifelse(is.na(colname1), NA, ifelse(is.na(colname2), 0, colname2)),
total = colname1 + colname2)
你得到:
# 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
当NA
不是colname2
时(如您所需的输出中所示),colname1
NA
中有0而不是{{1}}