For those who may be interested (and also familiar with Python), check out the fuc.pyvcf submodule I wrote:
Below is a simple example that (I believe) achieves what the original post was asking.
>>> from fuc import pyvcf
>>> data = {
... 'CHROM': ['chr1', 'chr1', 'chr1', 'chr1', 'chr1'],
... 'POS': [100, 101, 102, 103, 104],
... 'ID': ['.', '.', '.', '.', '.'],
... 'REF': ['G', 'T', 'A', 'C', 'C'],
... 'ALT': ['A', 'C', 'T', 'A', 'T'],
... 'QUAL': ['.', 24, 39, 15, 30],
... 'FILTER': ['.', '.', '.', '.', '.'],
... 'INFO': ['.', '.', '.', '.', '.'],
... 'FORMAT': ['GT:DP', 'GT:DP', 'GT:DP', 'GT:DP', 'GT:DP'],
... 'Steven': ['0/0:11', '1/1:8', '0/1:15', '0/1:17', '1/1:3'],
... 'Rachel': ['0/1:8', '0/0:23', '0/0:7', '0/1:15', '1/1:12'],
... }
>>> vf = pyvcf.VcfFrame.from_dict([], data)
>>> vf.df
CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Steven Rachel
0 chr1 100 . G A . . . GT:DP 0/0:11 0/1:8
1 chr1 101 . T C 24 . . GT:DP 1/1:8 0/0:23
2 chr1 102 . A T 39 . . GT:DP 0/1:15 0/0:7
3 chr1 103 . C A 15 . . GT:DP 0/1:17 0/1:15
4 chr1 104 . C T 30 . . GT:DP 1/1:3 1/1:12
We first select rows with QUAL >= 30:
>>> filtered_vf = vf.filter_qual(30)
>>> filtered_vf.df
CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Steven Rachel
0 chr1 102 . A T 39 . . GT:DP 0/1:15 0/0:7
1 chr1 104 . C T 30 . . GT:DP 1/1:3 1/1:12
Next, we mark genotypes with DP < 10 as missing:
>>> filtered_vf = filtered_vf.markmiss_dp(10, full=True)
>>> filtered_vf.df
CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Steven Rachel
0 chr1 102 . A T 39 . . GT:DP 0/1:15 ./.:.
1 chr1 104 . C T 30 . . GT:DP ./.:. 1/1:12