【问题标题】:Select rows based on condition from each column根据每列的条件选择行
【发布时间】:2018-01-24 13:15:07
【问题描述】:

我有我正在为实验室分析的数据,并且我是第一次尝试使用 R。

我一直在阅读有关根据条件选择行的内容,但我似乎找不到为我的数据执行此操作的方法。

我制作了一个数据框,但没有命名列。每一列都是我正在测试的一种细菌的特定变体,它的 OD/吸光度值在大约 15 小时内不断增加(每列总共 56 行)。

我想从每个列中选择值范围为 0.2 到 0.4 的行。

所以理想情况下我想要这样的东西:

   V1       V2
9  0.2100  7 0.2181
10 0.3017  8 0.3162
11 0.4079  9 0.4137

等等

我想我可以从每一列中手动选择行,但必须有更快的方法。

然后我计划计算子集的每一列的平均值。

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 欢迎来到 StackOverflow!请阅读有关how to ask a good question 的信息以及如何提供reproducible example。这将使其他人更容易帮助您。
  • 您可以尝试lapply(df1, function(x) x[x > 0.2 & x < 0.4]) 并将其保存在list 中,因为每列中符合条件的元素数量可能会有所不同
  • 如果您只想要这些方法,请使用sapply(df, function(x) mean(x[x > .2 & x < .4]))。这样,您将获得长度为 ncol(df) 的向量,其中包含每列子集的平均值。
  • @LAP 太棒了,非常感谢!但是我如何结合你的两个答案呢?更具体地说,我只想要最接近 0.3 的值,然后是它周围的 2 个值,所以在 0.2 和 0.4 左右,但我只想要 3 个值。正如 akrun 建议的那样,某些列中的元素数量不同。如何确保 sapply 平均值适用于 3 个值?

标签: r subset


【解决方案1】:

这样就可以了:

findNearest3 <- function(x, y, z){
  temp <- sort(x[x > z[1] & x < z[2]])
  point <- which(abs(temp-y)==min(abs(temp-y)))
  return(temp[c(point-1, point, point+1)])
}

该函数将在向量x 中查找与y 最接近的值,受限制z 约束,并返回该值加上排序向量中前后的值。

例子:

set.seed(123)
df <- data.frame(x = rnorm(100), y = rnorm(100))

sapply(df, findNearest3, .3, c(.2, .4))
             x         y
[1,] 0.2533185 0.2982276
[2,] 0.3035286 0.3011534
[3,] 0.3317820 0.3104807

现在有

sapply(df, function(x) mean(findNearest3(x, .3, c(.2, .4))))

你会得到手段:

        x         y 
0.2962097 0.3032872 

请注意,如果给定约束 z 内没有足够的值,这将返回 NA

df <- data.frame(x = c(.1, .23, .35, .5), y = c(.22, .24, .33, .48))

> sapply(df, findNearest3, .3, c(.2, .4))
        x    y
[1,] 0.23 0.24
[2,] 0.35 0.33
[3,]   NA   NA

> sapply(df, function(x) mean(findNearest3(x, .3, c(.2, .4)), na.rm = T))
    x     y 
0.290 0.285 

编辑:要返回值的行位置而不是值本身,只需更改代码的最后一行:

findNearest3.pos <- function(x, y){
  temp <- sort(x)
  point <- which(abs(temp-y)==min(abs(temp-y)))
  return(c(point-1, point, point+1))
}

应用: 要在另一个相同维度的数据框上使用它,首先将位置保存在列表中:

myrows <- lapply(df, findNearest3.pos, y = .3)

然后子集第二个数据帧:

set.seed(234)
df1 <- data.frame(x = rnorm(100), y = rnorm(100))

newsubset <- mapply(function(x, y) x[y], df1, myrows)
              x        y
[1,] -0.9581388 2.214151
[2,]  0.6280635 0.455070
[3,]  0.6625872 0.513053

考虑到只有一列的其他数据框,您需要决定要使用哪一列的行位置。

set.seed(345)
df2 <- data.frame(x = rnorm(100))

您可以通过以下方式访问在V1(或在本例中为x)中找到的行位置:

df2[myrows[[1]],]
[1]  0.2986353 -0.9917691 -0.6510206

以及在V2(此处命名为y)中找到的那些:

df2[myrows[[2]],]
[1] -0.3148442 -0.2491949  0.6854260

【讨论】:

  • 谢谢!但我认为出于我的目的,您发布的代码的早期版本效果更好,因为我不需要 3 左右的值正好在 0.2 和 0.4 之间,因为 ~0.3 之后的一些值可以达到 0.46 左右。有了额外的 c(.2, .4),我得到了太多的 NA。
  • 如果您不介意,您能帮我解决另一个问题吗?我想知道这些 3 个值的集合在每列中的哪些行,例如在第 1 列中,它们是第 7、8、9 行,但在第 2 列中,它们是第 8、9、10 行,依此类推。然后我想在具有相同维度的不同数据框中选择相应的行,因此在这种情况下,~0.2、~0,3、~0.4 的值不相关,然后再次计算平均值。谢谢!
  • 您可以将z[x &gt; z[1] &amp; x &lt; z[2]] 排除在函数之外以不受限制地使用它。我会处理您的其他请求,并将解决方案编辑到我的答案中。
  • 非常感谢您的解决方案!那么如何获取行位置以在另一个数据框中找到相应的行呢?我还有 2 个其他数据框 - 一个与我一直使用的具有相同的尺寸,然后另一个只有 1 列但具有相同的行数。
  • 谢谢!!!到目前为止一切正常,但是对于单列数据框,我想使用第一个数据框中的每一列,我认为其中大约有 66 列。现在我有这个: set.seed(345) mean(time_hr[myrows[[1]],]) mean(time_hr[myrows[[2]],]) mean(time_hr[myrows[[3]] ,]) mean(time_hr[myrows[[4]],]) mean(time_hr[myrows[[5]],]) mean(time_hr[myrows[[6]],]) 等等。有没有办法将这些组合成一个列表/数据框?
【解决方案2】:

在此示例中,您将获得一个列表,其中每个变量的值向量在 0.2 到 0.4 之间。希望对你有帮助

df=data.frame(V1=c(1,0.3,2,.1,.5,8,.1,.4,.35,.22,6),V2=c(0.2,0.3,3,.15,.32,5,.1,.45,.35,.3,6))
filteredColumns<-sapply(df,function(x) x[x>0.2&x<0.4])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多