我在R中有一个需要清洁的数据框。问题在于数据在值内(在引号内;它对应于列名)具有相应的列名。然后,我只想将数字值保留在:
的右边。
这是原始数据框:
> df
col1 col2 col3 col4
1 "4":50 "2":10 "1":0 "3":20
2 "2":5 "4":-50
3 NULL
4 "4":65 "3":45 "2":-15 "1":0
所需的输出:
> new_df
col1 col2 col3 col4
1 0 10 20 50
2 0 5 0 -50
3 NULL
4 0 -15 45 65
为方便起见,这是dput(df)
的输出。
dput(df)
structure(list(`1` = c("\"4\":50", "\"2\":5", "NULL", "\"4\":65"
), `2` = c("\"2\":10", "\"4\":-50", "", "\"3\":45"), `3` = c("\"1\":0",
"", "", "\"2\":-15"), `4` = c("\"3\":20", "", "", "\"1\":0")), class = "data.frame", row.names = c(NA,
-4L))
答案 0 :(得分:0)
这是一个数据框,该数据框与该数据框尽可能接近。所有行都必须具有值或NA,因此第三行必须具有:
3 "NULL" "" "" ""
引号和分隔符需要特别处理,因为使用read.table
很难输入数据安排:
df <- read.table(text=' col1, col2, col3, col4
1, "4":50 , "2":10 , "1":0, "3":20
2, "2":5, "4":-50
3, NULL
4 , "4":65, "3":45, "2":-15, "1":0', sep=",", header=TRUE,quote="\"",fill=TRUE,strip.white=TRUE)
现在可以分别在每一行上工作,并将值放置在键的位置:
我的第一次尝试是:
df2 <- apply(df, 1, function(x) if(x=="NULL"){ c("NULL",NA,NA,NA) } else
{ z <- rep(0,4)
for (i in x){
z[as.numeric(sub( ":.+$", "", i))] <- sub("^.+:", "", i) }
return(z)})
如果从侧面看,这几乎是正确的。由于R以{列大”的形式返回apply
的结果,因此您通常需要转置:
df3 <- t(df2)
df3
[,1] [,2] [,3] [,4]
1 "0" "10" "20" "50"
2 "0" "5" "0" "-50"
3 "NULL" NA NA NA
4 "0" "-15" "45" "65"
@ Z.Springirth:请不要抱怨这些是字符值。您是在此输出中指定“ NULL”值的人。 “ NULL”不是合法的数值,并且数据框中的列必须属于同一类。因此,一列中的一个字符值会强制所有值成为字符。
这使您看起来很成功,但我警告您,列是因素而不是特征。除非您(单独)将其强制转换为数字,否则这些条目的行为不会像数字:
> as.data.frame(df3)
V1 V2 V3 V4
1 0 10 20 50
2 0 5 0 -50
3 NULL <NA> <NA> <NA>
4 0 -15 45 65
如果您愿意放弃“ NULL”要求,则可以完成该过程:
> df4 <- as.data.frame(df3,stringsAsFactors=FALSE)
> df4[] <- lapply(df4, as.numeric)
Warning message:
In lapply(df4, as.numeric) : NAs introduced by coercion
> df4
V1 V2 V3 V4
1 0 10 20 50
2 0 5 0 -50
3 NA NA NA NA
4 0 -15 45 65