2
$\begingroup$

I am comparing genomic profiles of identical samples and I need to extract the paired samples from a listing of all samples, so as an illustration how can I adapt "How can I get list of duplicates...." to this problem of keeping only lists that have duplicated samples.

{{sample1,2},{sample1,3},{sample2,3},{sample3,4},{sample3,6}}

=>

{{sample1,2},{sample1,3},{sample3,4},{sample3,6}}

$\endgroup$
0

4 Answers 4

1
$\begingroup$

On my machine, the following

F[list_] := Flatten[Select[Gather[list, First[#1] == First[#2] &], Length[#] > 1 &], 1]

is faster than

G[list_] := Flatten[Cases[GroupBy[list, First], {_, __}], 1]

although I am not entirely sure why: I suspect it has to do with pattern matching being slower. When the number of unpaired samples is large, the evaluation time discrepancy increases.

$\endgroup$
1
  • $\begingroup$ Kuba's use of GroupBy was unnecessary and counterproductive. I corrected his answer to use GatherBy instead and it is now much faster. $\endgroup$
    – Mr.Wizard
    Feb 7, 2017 at 18:53
7
$\begingroup$
list = {{sample1, 2}, {sample1, 3}, {sample2, 3}, {sample3, 
   4}, {sample3, 6}}

Flatten[Cases[GatherBy[list, First], {_, __}], 1]
{{sample1, 2}, {sample1, 3}, {sample3, 4}, {sample3, 6}}

So for

list = {{sample1, 1}, {sample2, 1}}

we will get

{}

as there are no duplicates in sample*.

$\endgroup$
5
  • $\begingroup$ Much more elegant than what I had in the mean time Select[list, Count[Flatten@list, First@#] > 1 &] $\endgroup$
    – Feyre
    Feb 7, 2017 at 12:06
  • $\begingroup$ @Feyre A matter of preference I suppose ;) $\endgroup$
    – Kuba
    Feb 7, 2017 at 12:09
  • 1
    $\begingroup$ As of 10.0, there's Catenate for Flatten[..., 1]. $\endgroup$ Feb 7, 2017 at 13:24
  • $\begingroup$ @MartinEnder and Join @@ is sometimes faster than either, e.g. if the input list is a packed array in this case, so it is still often my first choice. $\endgroup$
    – Mr.Wizard
    Feb 7, 2017 at 18:58
  • 1
    $\begingroup$ @Mr.Wizard I used GroupBy, I could have bet it wasn't the case. Thanks for correction of that typo :) $\endgroup$
    – Kuba
    Feb 7, 2017 at 19:02
3
$\begingroup$

I recommend using DeleteDuplicatesBy for this task.

data = {{sample1, 2}, {sample1, 3}, {sample2, 3}, {sample3, 4}, {sample3, 6}};
DeleteDuplicatesBy[data, Last]

{{sample1, 2}, {sample1, 3}, {sample3, 4}, {sample3, 6}}

$\endgroup$
2
  • 2
    $\begingroup$ I think OP picked unfortunate example because the point is to keep entries which appear more than once base on the first element. So {{sample1,1},{sample2,1}} shoul be left empty while your method will give {{sample1,1}} $\endgroup$
    – Kuba
    Feb 7, 2017 at 12:01
  • $\begingroup$ @Kuba. I think you're right. $\endgroup$
    – m_goldberg
    Feb 8, 2017 at 1:16
0
$\begingroup$
list = {{sample1, 2}, {sample1, 3}, {sample2, 3}, {sample3, 4}, {sample3, 6}};

Using SequenceSplit (new in 11.3)

SequenceSplit[list, {a : {_, b_}, {_, b_} ...} :> a]

{{sample1, 2}, {sample1, 3}, {sample3, 4}, {sample3, 6}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.