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
$\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$
  • $\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 '17 at 18:53
6
$\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$
  • $\begingroup$ Much more elegant than what I had in the mean time Select[list, Count[Flatten@list, First@#] > 1 &] $\endgroup$ – Feyre Feb 7 '17 at 12:06
  • $\begingroup$ @Feyre A matter of preference I suppose ;) $\endgroup$ – Kuba Feb 7 '17 at 12:09
  • 1
    $\begingroup$ As of 10.0, there's Catenate for Flatten[..., 1]. $\endgroup$ – Martin Ender Feb 7 '17 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 '17 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 '17 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
    $\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 '17 at 12:01
  • $\begingroup$ @Kuba. I think you're right. $\endgroup$ – m_goldberg Feb 8 '17 at 1:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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