外观
样本敏感性
按确切数量、保护规则和面板个体生成样本。
核心代码
py
def sample_ids(self, spec):
sample = spec.get('sample') or {'kind': 'none'}
frame = self.reference
c, kind = self.config, sample['kind']
protected = set(c['protected_rows'])
if c['entity']:
protected.update(frame.index[frame[c['entity']].astype(str).isin(c['protected_entities'])].tolist())
if kind == 'none':
return self.ref_ids
if kind == 'drop_rows':
drop = set(sample['values'])
elif kind == 'drop_entities':
drop = set(frame.index[frame[c['entity']].astype(str).isin(sample['values'])])
elif kind == 'short_panels':
sizes = frame.groupby(c['entity'])[c['entity']].transform('size')
drop = set(frame.index[sizes < sample['minimum']])
elif kind in ('random_rows', 'random_entities'):
rng = np.random.default_rng(sample['seed'])
if kind == 'random_rows':
pool = sorted(set(self.ref_ids) - protected)
n = int(len(frame) * sample['drop_fraction'])
if n > len(pool):
raise ExplorationError('protected_sample')
drop = set(map(int, rng.choice(pool, n, replace=False)))
else:
entities = sorted(frame[c['entity']].astype(str).unique())
locked = set(frame.loc[frame.index.isin(protected), c['entity']].astype(str))
pool = sorted(set(entities) - locked)
n = int(len(entities) * sample['drop_fraction'])
if n > len(pool):
raise ExplorationError('protected_sample')
chosen = list(rng.choice(pool, n, replace=False))
drop = set(frame.index[frame[c['entity']].astype(str).isin(chosen)])
else:
raise ExplorationError('invalid_sample')
if drop & protected:
raise ExplorationError('protected_sample')
return [i for i in self.ref_ids if i not in drop]