【问题标题】:Group values in one dataframe based on range in columns in another dataframe根据另一个数据框中的列范围对一个数据框中的值进行分组
【发布时间】:2019-03-28 04:57:00
【问题描述】:

我有一个数据框:

structure(list(PS_position = c(1000L, 1050L, 1100L, 2000L, 3000L, 
4000L, 5000L, 6000L, 7000L, 8000L, 8500L, 9000L, 9050L, 9001L, 
9051L, 9002L, 9052L, 9003L, 9053L, 9004L, 9054L, 9001L, 9051L, 
9002L, 9052L, 9003L, 9053L, 10000L, 9000L, 9200L, 9340L, 9350L, 
9550L, 9560L), Region_ID = c("BRCA", "BRCA", "BRCA", "BRCA", 
"BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", 
"BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", 
"BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", "BRCA", 
"WNT", "WNT", "WNT", "WNT", "WNT", "WNT"), SNP_ID = c(123455L, 
123456L, 123457L, 123458L, 123459L, 123460L, 123461L, 123462L, 
123463L, 123464L, 123465L, 123466L, 123467L, 123468L, 123469L, 
123470L, 123471L, 123472L, 123473L, 123474L, 123475L, 123476L, 
123477L, 123478L, 123479L, 123480L, 123481L, 123482L, 56789L, 
56790L, 56795L, 56796L, 56816L, 56817L), chr_key = c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), probe_type = c("preselected", "preselected", "preselected", 
"preselected", "preselected", "preselected", "preselected", "preselected", 
"validated", "validated", "validated", "validated", "validated", 
"validated", "validated", "validated", "unvalidated ", "unvalidated ", 
"unvalidated ", "unvalidated ", "unvalidated ", "unvalidated ", 
"unvalidated ", "unvalidated ", "non_polymorphic", "non_polymorphic", 
"non_polymorphic", "non_polymorphic", "preselected", "preselected", 
"preselected", "unvalidated ", "non_polymorphic", "validated"
)), class = "data.frame", row.names = c(NA, -34L))

我想总结PS_position 列中的行。

通常我会这样做:

out_df <- setNames(data.frame(matrix(ncol = 1, nrow=length(unique(selection$Region_ID)))), c("Region_ID"))
out_df$Region_ID <- unique(unique(selection$Region_ID))
    x <- selection %>% 
  group_by(Region_ID) %>%
  summarise(num_probesets = length(probe_type))

out_df <- merge(out_df, x, by="Region_ID")

y <- df %>% 
  group_by(Region_ID, probe_type) %>%
  summarise(num_probesets = length(probe_type))

y_wide <- spread(y, probe_type, num_probesets)

out_df <- merge(out_df, y_wide, by="Region_ID")

这给出了以下结果:

structure(list(Region_ID = c("BRCA", "WNT"), num_probesets = c(28L, 
6L)), row.names = c(NA, -2L), class = "data.frame")

但是,Region_IDgroup_by 缺少一个事实,即基于此数据框,PS_position 的某些值可能出现在两个区域中。因此,我想从以下数据框中的 >=start 和 stop 位置总结PS_position

structure(list(region_name = c("BRCA", "WNT"), gene_symbol = c("BRCA", 
"BRCA"), chr = c(1L, 1L), start = c(1000L, 9000L), stop = c(10000L, 
10000L), resolution = c("fixed", "fixed"), genome_build = c("hg38", 
"hg38"), Notes = c(NA, NA), overlap = c("no_overlap", "no_overlap"
), length_of_region = c(9000L, 1000L), length_of_region_plus_flanks = c(10000L, 
2000L), region_probesets = c(50L, 50L), flank_start_left = c(499L, 
8499L), flank_stop_left = c(999L, 8999L), flank_start_right = c(10001L, 
10001L), flank_stop_right = c(10501L, 10501L), flank_length_left = c(500L, 
500L), flank_length_right = c(500L, 500L), flank_probes_right = c(10L, 
10L), flank_probes_left = c(10L, 10L), total_expected_probesets = c(70L, 
70L), critical_error = c(FALSE, FALSE), flank_name_left = c("BRCA_left", 
"WNT_left"), flank_name_right = c("BRCA_right", "WNT_right"), 
    countrgn = c(50L, 50L)), class = "data.frame", row.names = c(NA, 
-2L))

因此,我的最终输出应如下所示:

structure(list(Region_ID = c("BRCA", "WNT"), num_probesets = c(34L, 
23L)), row.names = c(NA, -2L), class = "data.frame")

关于如何做到这一点的任何想法?

【问题讨论】:

  • 如果您提供了所需的最终输出,将会有所帮助。从代码中不清楚您到底要做什么。
  • 如果您不仔细表达问题并明确说明什么是更好的结果,就很难提供满足您需求的替代方案。请不要通过在 cmets 中回复来做新手的事情。使用edit
  • Ewwww。我喜欢。在过去(可能是一年或更早),将[edit] 放入评论中将需要一个描述编辑工具的 SO 页面。现在它将用户点击器放入该页面的特定编辑框架中。
  • 嗨,我已经完全更新了示例,包括所需输出的示例

标签: r dataframe range


【解决方案1】:

试试这个:

#create a df with just the start and stop variables
start_stop <- df2 %>% 
  select(region_name, start, stop) 

df %>% 
  merge(start_stop) %>% #Cartesian join
  mutate(Region = ifelse(PS_position >= start & PS_position <= stop, region_name, NA)) %>% #assigns a region to each record based on PS_position
  filter(!is.na(Region)) %>% #drop NAs 
  group_by(Region) %>% 
  summarise(num_probesets = n()) %>% #count number of records by Region
  rename(Region_ID = Region) %>% #rename to join later
  ungroup() %>% 
  left_join( #left join with a df that counts the probe_type by Region_ID
    df %>% 
  group_by(Region_ID, probe_type) %>%
  summarise(num = n()) %>% 
  spread(probe_type, num) %>% 
  ungroup()
  )

【讨论】:

  • 嗨!感谢您的回答。所以我想要基于上面输出的第二个数据框中的min(start)min(stop) 列的值,而不是min(PS_position) 本身。
  • 你能解释一下第二个dataframe 与第一个的关系吗?是否要将第二个 dataframe 加入到第一个处理后的输出中并获得 min(start)min(stop) 值?
  • 它具有相同的Region_ID,并且所有PS_positions 将位于每个区域第二个数据帧的start / stop
  • 查看我的编辑 - 如果这是您要查找的内容,我可以添加更多详细信息。
  • 是的,这个答案很完美!你能解释一下吗?我还做了一堆其他的总结,比如max_gap_length &lt;- df %&gt;% group_by(Region_ID) %&gt;% mutate(Diff = PS_position - lag(PS_position)) %&gt;% na.omit() %&gt;% summarise(max_gap_length = max(Diff)) 得到max_gapmin_gapavg_gap 得到PS_positions 之间的距离(再次按Region_ID 分组。这个解决方案也应该有助于我想想。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
相关资源
最近更新 更多