我有一个包含48列的大型数据框,我想在数据帧的每一行上运行一个函数,通过该函数给出的测试的列设置为NA。此测试涉及从另一个数据框中获取数字。 adply很适合这种情况,但我遇到问题就是给我一些我想要的结果。
让我解释一下:
以下是我想要操作的数据框的示例:
>df
pt depth Cell1_avgvel Cell1_avgdir Cell2_avgvel Cell2_avgdir
1 1 0.1 NA NA NA NA
2 2 0.2 NA NA 1.344 324.0
3 3 0.3 NA NA 0.445 167.0
4 4 0.4 1.455 354.2 0.322 321.2
以下是从中派生测试的小数据框:
> tcell
depth name
1 0.2 Cell1
2 0.4 Cell2
3 0.6 Cell3
4 0.8 Cell4
整个想法是将NA分配给比大数据帧中列出的实际深度更深的单元格的数据点(即在第3行中,深度为0.3但是有两个数据点对应于Cell2,这是0.4米的深度,因此这些都是错误。我想NA这些。)
我想编写一个一次排成一行的函数,并且: 1)抓住仪器深度 2)获取列名列表 3)获得比仪器深度更深的细胞指数 4)获取那些单元格的名称(即Cell1,Cell2,Cell4等) 5)使用正则表达式查找列名列表中具有相应单元格的列(即Cell1_avgdir,Cell1_avgvel等) 6)使用这些索引,将这些列值设置为NA。
这是我到目前为止所拥有的:
depthNA = function(x) {
depth = x$depth
nms = names(df)
ind = as.character(which(depth < tcell$depth))
c = tcell$name[ind]
patt = paste(c,collapse="|")
c_ind = grep(patt,nms)
x[,c_ind] <- NA
}
adply(df,1,depthNA)
不幸的是,这并没有按照我的想法行事,我现在不知道为什么会这样做。
它给了我这个:
pt depth Cell1_avgvel Cell1_avgdir Cell2_avgvel Cell2_avgdir V1
1 1 0.1 NA NA NA NA NA
2 2 0.2 NA NA 1.344 324.0 NA
3 3 0.3 NA NA 0.445 167.0 NA
4 4 0.4 1.455 354.2 0.322 321.2 NA
当我想要的是:
pt depth Cell1_avgvel Cell1_avgdir Cell2_avgvel Cell2_avgdir
1 1 0.1 NA NA NA NA
2 2 0.2 NA NA NA NA
3 3 0.3 NA NA NA NA
4 4 0.4 1.455 354.2 0.322 321.2
希望我已经充分解释了我的问题。感谢任何人可以:1)修复我已经开始的事情,或者2)告诉我一个更好的方法去做,我不知道。
-SH
答案 0 :(得分:1)
以下是一个答案,可以回答您的想法概述但与您的输出不符。请参阅上面关于输出是否正确的评论。答案取决于reshape2
,使加入更容易。
首先,我用以下内容阅读您的数据:
df <- read.table(text = " pt depth Cell1_avgvel Cell1_avgdir Cell2_avgvel Cell2_avgdir
1 1 0.1 NA NA NA NA
2 2 0.2 NA NA 1.344 324.0
3 3 0.3 NA NA 0.445 167.0
4 4 0.4 1.455 354.2 0.322 321.2", header = TRUE)
tcell <- read.table(text = " depth name
1 0.2 Cell1
2 0.4 Cell2
3 0.6 Cell3
4 0.8 Cell4", header = TRUE)
然后解决你的问题:
library(reshape2)
#Melt into long format
df.m <- melt(df, id.vars = 1:2)
#Split the column into two new columns based on _
df.m[, c("Cell", "OtherCol")] <- with(df.m, colsplit(variable, "_", c("Cell", "OtherCol")))
#Merge together with tcell
df.m <- merge(df.m, tcell, by.x = "Cell", by.y = "name")
#Add a new column which sets the offending values to NA
df.m <- transform(df.m, newvalue = ifelse(value > depth.y, NA, value))
#Cast back into wide format
dcast(pt + depth.x ~ variable, value.var = "newvalue", data = df.m)
pt depth.x Cell1_avgvel Cell1_avgdir Cell2_avgvel Cell2_avgdir
1 1 0.1 NA NA NA NA
2 2 0.2 NA NA NA NA
3 3 0.3 NA NA NA NA
4 4 0.4 NA NA 0.322 NA