【问题标题】:Filter datapoints in a scatterplot using a linear equation使用线性方程过滤散点图中的数据点
【发布时间】:2021-01-28 08:23:04
【问题描述】:

我正在编写一个函数,以便根据线性方程从我的图中过滤掉数据点。 我目前有以下功能(其中包含不同的功能):

 MD_filter<- function(dataframe, mz_col){ 
    #In-function MD calculation
    MZ<- mz_col
    MZR<- trunc(mz_col, digits = 0)#Either floor() or trunc() can be used for this part.
    MD<- as.numeric(MZ-MZR)
    dataframe<- dataframe%>%
      dplyr::mutate(MD)%>%
      dplyr::select(MD, everything())
    #fit data to m/z defect maxima equation
    f<- function(x){#This could be problem `1`, maybe resolved by leaving x.... 
      y<-0.00112*x + 0.01953
      return(y)}
    fit<-as.data.frame(t(apply(dataframe,1,f)))# t() transforms df to matrix...?
    filtered<-dataframe[which((dataframe$MD<= fit$MZ)),]
    #keep rows in dataframe if MD is less than or equal to fitted value (mz after equation)
    #As "fit" calculated the maximum MD value for each MZ value in the MZ column, we subset fit$MZ, as this contains the dataframe MZ values.
    #The MD calculated at the very start, needs to be lower than the equivalent MZ value of the fitted dataframe.
    filtered<-write.table(filtered,"feature_list_mz_defect_filtered.txt",sep="\t",col.names=NA)
    #Now we have pre filter dataframe (dataframe) and post filter df (filtered)
    #2 Different plots: (highlight to be removed as well, so we need a 3rd eventually)
    MD_plot<- ggplot(dataframe, aes(x= MZ, y = MD)) +
      geom_point() +#THE FOLLOWING PART DOES NOT WORK YET
      ggtitle(paste("Unfiltered MD data - ", dataframe))
    #stat_smooth(method="lm", se=FALSE)-> For linear line through the plot, but may not be necessary to show
    
    return(MD_plot)#While I do get a plot, I have not yet gotten the equation. I could use my earlier approach maybe.
    
    MD_plot_2<- ggplot(filtered, aes(x= MZ, y = MD)) +#Filtered is basically the second dataframe, 
      #which subsets datapoints with an Y value (which is the MD), below the linear equation MD...
      geom_point() +#THE FOLLOWING PART DOES NOT WORK YET
      ggtitle(paste("Filtered MD data - ", dataframe))
    #stat_smooth(method="lm", se=FALSE) -> For linear line through the plot, but may not be necessary to show
    
    return(MD_plot_2)
    
  }

函数的工作原理如下: 参数输入是一个数据框和该数据框内的一个特定列,我称之为 mz_col。 从此列生成第二列,即 MD 列。

从这里开始,我想制作两个情节: ggplot 1:X 轴为 mz_col (MZ) 值,Y 轴为 MD 值的绘图

ggplot 2:与 ggplot 1 完全相同,但如果 MD 超过线性方程 y

我尝试了许多不同的解决方案。我在许多其他解决方案中用 mz_col 交换了“x”参数,例如尝试使用 plot() 而不是 ggplot。目前我没有得到任何情节,但我确实得到了这个:

基本上我的问题是:我如何解决我的功能,所以我可以得到我的两个情节?第一个图不是真正的问题,这已经有效,但第二个图不会根据我的线性方程过滤掉数据点。

提前致谢!我对 SO 和 R 很陌生,所以如果有任何不清楚的地方,我深表歉意。如果需要任何澄清,请告诉我,并提前感谢所有帮助!

可重现的样本数据:

structure(list(mz = c(446.0394, 346.043, 199.0446, 199.0464, 97.057, 657.0595, 879.0606, 978.0631, 199.0684, 199.0707, 199.0724, 86.0748, 199.0761, 196.0789, 199.0819, 199.0852, 199.0878, 199.089, 908.0935, 147.0958, 199.0999,199.1299, 199.1322, 199.1384, 199.1398, 199.1434, 124.1475, 199.1513, 187.156, 199.1686, 199.1766, 199.1797, 199.1879, 199.1924, 187.1959, 479.1981, 169.1999, 109.2049, 399.2092, 299.2125, 159.2146, 199.2242, 356.2405, 69.2423, 956.4337, 978.5537, 199.5695, 676.5769, 199.5851, 500.6021, 260.6039, 270.6081, 200.6114, 200.6131, 200.6172, 200.6221, 
200.6315, 200.6402, 200.6476, 200.766, 200.8591, 200.8732, 200.8768, 
200.89, 200.8937, 200.8972, 200.9067, 200.9127, 200.9147, 200.9231, 
200.9253, 200.9288, 200.9324, 200.935, 200.9468, 200.9515, 200.9536, 
200.9557, 200.9568, 200.9594, 200.9661, 200.968, 200.9729, 200.9745, 
200.9819, 200.9837, 200.9858, 200.9937)), row.names = c(NA, -88L), class = c("tbl_df", "tbl", "data.frame"))

【问题讨论】:

  • 您能否分享一个可重现的小示例,以便我们可以运行您的功能? dput() 有助于制作 R 对象的复制/可粘贴版本 - 或使用内置数据集,或共享代码来模拟一点假数据。示例数据越简单,问题就越清晰。
  • 但是,一目了然 - 只要有 return(),R 函数就会结束。与其return创建第一个情节,不如等到最后再return(list(MD_plot, MD_plot_2))
  • 投票结束对工作示例数据的有力请求(2小时后)没有回应。海报应监测 cmets 并及时作出回应。
  • 对于我迟到的回复,我深表歉意,当我发布这个问题时,我住的地方已经是凌晨 2 点了,没想到会这么快得到答复。我目前正在弄清楚 dput 的用途,我将在 15 分钟内发布我的示例数据。
  • 结构(列表(MZ = C(446.0394,246.043,199.046,657.0595,879.0606,978.0631,199.0684,99.0707,199.0761,196.0789.0761,19.0789,199.0819,199.0852,199.0878, 199.089,908.0935,147.0958,199.0999,199.1299,199.1322,199.1384,199.1398,199.1434,124.1475,199.1513,187.156,199.1686,199.1766,199.1797,199.1879,199.1924,187.1959,479.1981,169.1999,109.2049,399.2092,299.2125,159.2146,199.2242, 356.2405, 69.2423, 956.4337, 978.5537, 199.5695, 676.5769, 199.5851)), row.names = c(NA, -49L), class= c("tbl_df", "tbl", "data.frame"))

标签: r dataframe ggplot2 plot functional-programming


【解决方案1】:

我在尝试遵循您的代码时有点迷失,但根据您的描述,以下内容对您有用吗?

library(dplyr)
library(ggplot2)

MD_filter <- function(dataframe, mz_col, a = 0.01953, b = 0.00112){ 
  
  # rename column so that rest of function doesn't depend on inputted column name
  dataframe[["MZ"]] <- dataframe[[mz_col]] 
  
  # process dataframe
  dataframe <- dataframe %>%
    select(MZ) %>%
    mutate(MD = MZ - trunc(MZ, digits = 0),
           MD.limit = a + b*MZ)
  
  p1 <- ggplot(dataframe,
               aes(x = MZ, y = MD)) +
    geom_point() +
    geom_smooth(method = "lm", se = F) +
    ggtitle("Unfiltered MD data")
  
  p2 <- p1 %+% filter(dataframe, MD <= MD.limit) +
    expand_limits(y = range(dataframe[["MD"]])) + # optional (if you want same 
                                                  # y-axis range for both plots)
    ggtitle("Filtered MD data")

  cowplot::plot_grid(p1, p2, nrow = 1)
}

数据和使用情况

dd <- structure(list(mz = c(
  446.0394, 346.043, 199.0446, 199.0464, 97.057, 657.0595, 879.0606, 
  978.0631, 199.0684, 199.0707, 199.0724, 86.0748, 199.0761, 196.0789, 
  199.0819, 199.0852, 199.0878, 199.089, 908.0935, 147.0958, 199.0999,
  199.1299, 199.1322, 199.1384, 199.1398, 199.1434, 124.1475, 199.1513, 
  187.156, 199.1686, 199.1766, 199.1797, 199.1879, 199.1924, 187.1959, 
  479.1981, 169.1999, 109.2049, 399.2092, 299.2125, 159.2146, 199.2242,
  356.2405, 69.2423, 956.4337, 978.5537, 199.5695, 676.5769, 199.5851,
  500.6021, 260.6039, 270.6081, 200.6114, 200.6131, 200.6172, 200.6221, 
  200.6315, 200.6402, 200.6476, 200.766, 200.8591, 200.8732, 200.8768, 
  200.89, 200.8937, 200.8972, 200.9067, 200.9127, 200.9147, 200.9231, 
  200.9253, 200.9288, 200.9324, 200.935, 200.9468, 200.9515, 200.9536, 
  200.9557, 200.9568, 200.9594, 200.9661, 200.968, 200.9729, 200.9745, 
  200.9819, 200.9837, 200.9858, 200.9937)),
  row.names = c(NA, -88L),
  class = c("tbl_df", "tbl", "data.frame"))

MD_filter(dd, "mz")
# MD_filter(dd, "mz", a = 0.02, b = 0.001) # if you want to change the limit

【讨论】:

  • 您好 Z.Lin 非常感谢您的帮助!我想我真的很接近解决我的问题,我目前得到这个:错误:必须提取具有单个有效下标的列。 x 由于精度损失,无法从 转换为 。运行rlang::last_error() 以查看错误发生的位置。我正在寻找解决方案,但如果您碰巧知道导致错误的原因,我很想知道。一旦我启动并运行了代码,我将发布它并接受您的答案作为解决方案,但您提供了巨大的帮助! :)
  • 你试过运行debug(name_of_your_function)吗?可能值得尝试查看哪条线路触发了问题。
  • 非常感谢!我真的从您的帖子中学到了很多东西,debug() 将来也可能对我有很大帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 2012-06-27
  • 2018-11-11
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
相关资源
最近更新 更多