【问题标题】:R - Identical values in columns of dataframe in one rowR - 一行中数据框列中的相同值
【发布时间】:2019-12-13 19:43:26
【问题描述】:

我有一个包含 3 列非整数值的数据框。分配时间的各个列中的值将与同一数据帧中其他一列或两列中的值相同。如果列之间存在匹配项,我希望它们位于同一行。

请参阅下面的 subset_dfexpected_subset_df 进行说明。

请注意,以 "248:-" 结尾的值在 expected_subset_df 的同一行中,但不在 subset_df 中。

摘要: col1 中的值也可以在 col2 和/或 col3 中。如果列之间的值确实匹配,我希望它们位于同一行。

> subset_df
         col1          col2          col3
1 20:31722330:- 20:31722330:- 20:31722330:-
2 20:31722348:- 20:31724051:- 20:31724051:-
3         FALSE 20:31722348:- 20:31722348:-
> expected_subset_df
         col1          col2          col3
1 20:31722330:- 20:31722330:- 20:31722330:-
2 20:31722348:- 20:31722348:- 20:31722348:-
3         FALSE 20:31724051:- 20:31724051:-

我的尝试

library(dplyr)
subset_df %>% 
    mutate_all(as.character) %>% 
        mutate(col1 = subset_df$col1[match(subset_df$col2, subset_df$col1)],
        col3 = subset_df$col3[match(subset_df$col2, subset_df$col3)])

产量:

         col1          col2          col3
1 20:31722330:- 20:31722330:- 20:31722330:-
2          <NA> 20:31724051:- 20:31724051:-
3 20:31722348:- 20:31722348:- 20:31722348:-

这种方法稳健吗?有更好的选择吗?

编辑:

假设数据框 breakpoint 如下所示:

> breakpoint
         col1           col2            col3
1 20:31722330:- 20:31722344:-            FALSE
2 21:15014555:- 21:15014555:-            FALSE
3 21:15014767:- 21:15014767:-    21:15014767:-

如何将数据帧 breakpoint 变成这样:

> expected_breakpoint
         col1           col2          col3
1 20:31722330:-          <NA>          <NA>
2          <NA>  20:31722344:-         <NA>
3 21:15014555:-  21:15014555:-         <NA>
4          <NA>          <NA>         FALSE
5          <NA>          <NA>         FALSE
6 21:15014767:-  21:15014767:-  21:15014767:-

编辑 2:分析前将FALSE 转换为&lt;NA&gt;

假设数据框 breakpoint_new 如下所示:

> breakpoint_new
         col1           col2            col3
1 20:31722330:- 20:31722344:-            <NA>
2 21:15014555:- 21:15014555:-            <NA>
3 21:15014767:- 21:15014767:-    21:15014767:-

如何将数据框 breakpoint_new 变成这样:

> expected_breakpoint_new
         col1           col2          col3
1 20:31722330:-          <NA>          <NA>
2          <NA>  20:31722344:-         <NA>
3 21:15014555:-  21:15014555:-         <NA>
4 21:15014767:-  21:15014767:-  21:15014767:-

【问题讨论】:

  • 在您的expected_breakpoint 中,您如何在第二行的“col2”中找到21:15014344:-。它没有显示在你输入的“断点”数据中
  • @akrun 错别字,已修复
  • col1 > col2 > col3 在没有匹配时向下移动的行数方面是否有优先级。在您之前的 expected_subset_df 中,FALSE 没有创建新行
  • @akrun 所有列都同等重要。我试图用expected_breakpoint 说明对于某些列中的某个值,该值试图与其他列中的值匹配。如果在其他列中找到匹配值,则将它们放在同一行上,否则将引入&lt;NA&gt;,表示未找到与其他数据帧中的任何值(在任何行上)的匹配。 FALSE 没有在 expected_subset_df 中创建新行是一个有效点。它确实不必重新排列。唯一的要求是 FALSE 保持不变。
  • FALSE 值在为自己创建新行后可以省略。它们不用于创建venn diagram。维恩图使用expected_breakpoint。列中的FALSE 仅表示该列没有此项,因此它不会显示在维恩图中。稍后我会将expected_breakpoint转换成二进制矩阵(字符串为TRUE,而FALSE或为FALSE)。

标签: r dataframe dplyr duplicates overlap


【解决方案1】:

以下函数解决了我的问题:

match_columns = function(df, nomatch=F){
  if (ncol(df) != 3){
    stop("Input DataFrame needs to have 3 columns")
  }
  matrix = matrix(ncol = 3, nrow = 0)
  match12 = intersect(df$object, df$object.1)
  match23 = intersect(df$object.1, df$object.2)
  match13 = intersect(df$object, df$object.2)


  for (item in match12){
    if (item == nomatch){next}
    if (item %in% match23){
      matrix = rbind(matrix, c(rep(item, 3)))
    }else{
      matrix = rbind(matrix, c(rep(item, 2), nomatch))
    }
  }

  for (item in match13){
    if (item == nomatch){next}
    if (!(item %in% match12)){
      matrix = rbind(matrix, c(item, nomatch, item))
    }
  }

  for (item in match23){
    if (item == nomatch){next}
    if (!(item %in% match13)){
      matrix = rbind(matrix, c(nomatch, rep(item, 2)))
    }
  }

  for (item in df$object){
    if (item == nomatch){next}
    if (!(item %in% match12) & !(item %in% match13)){
      matrix = rbind(matrix, c(item, rep(nomatch, 2)))
    }
  }

  for (item in df$object.1){
    if (item == nomatch){next}
    if (!(item %in% match12) & !(item %in% match23)){
      matrix = rbind(matrix, c(nomatch, item, nomatch))
    }
  }

  for (item in df$object.2){
    if (item == nomatch){next}
    if (!(item %in% match13) & !(item %in% match23)){
      matrix = rbind(matrix, c(rep(nomatch, 2), item))
    }
  }

  return(matrix)
}

它们各自列中的值与其他列中的相同值匹配。如果不是所有三列都匹配,则引入FALSE

【讨论】:

    猜你喜欢
    • 2021-03-18
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 2019-04-03
    相关资源
    最近更新 更多