This can be solved with a simple `groupby` operation, which can tell you how often each combination appears. Then you just need to compare this with your `n` and filter the data: key = ["begin", "end", "case"] n = len(systems) // 2 mask = df.groupby(key)["system"].count() > n df.set_index(key)[mask] \ .reset_index() \ .drop(columns="system") \ .drop_duplicates() # begin end case # 0 10 14 0365 This outputs the same as your code on my machine, but not the same as the example output you gave in your question (which I think is wrong). Note that I used integer division `//` instead of float division `/` and manually casting to `int`. In general, if you find yourself using `itertuples` in `pandas`, you should think very hard if you cannot achieve your goal in another way, as that is one of the slowest ways to do something with all rows of a dataframe.