Pandas每隔n个值采样一次,或者将最接近的匹配值采样到第n个值

时间:2017-11-17 01:03:11

标签: python pandas vectorization

我有一个特殊的问题。我有一个非常大的数据框,我正在尝试。

我的数据看起来像这样(两列x和y):

x,y
1,'a'
1,'b'
1,'c'
3,'a'
3,'b'
3,'c'
6,'a'
6,'b'
6,'c'

我想根据'x'的值进行采样。我想要每32个x值中的一个样本(基于x的变化,所以我想在1到32之间采样一次,即使x中只有一个值在1到32之间)。

我想做点什么:df[df['x'] % 32 == 0]。问题是x的值不一定是均匀间隔的(虽然它们是“近似”,但并非总是如此 - 例如在给出的例子中)。例如,如果特定子问题中x的所有值都是奇数,则上述采样将返回空数据帧。实际上,我想每32'x采样一次,或者将最接近的值取为第32个值(如果不存在这样的值,则可以接近最接近 - 例如,取下一个可用值是正常的)。

因此,如果我有一系列X [0, 10, 32, 39, 64, 70, 73, 74, 97, 100, 110, 129],我想对x值与[0, 32, 64, 97, 129]匹配的行进行抽样。

理想情况下,我也可以对此操作进行矢量化,因为数据帧通常非常大。

2 个答案:

答案 0 :(得分:1)

df = pd.DataFrame({'x': [1, 1, 1, 3, 3, 3, 6, 6, 6],
                   'y': ['a', 'b', 'c'] * 3})

x = [0, 10, 32, 39, 64, 70, 73, 74, 97, 100, 110, 129]
spacer = 32

X = pd.Series(x)
# For each value `n` in the range 0, 32, 64, ..., 129, find the index location of the 
# nearest value in X via `X.sub(n).abs().idxmin()`. Then use these index locations 
# to find the actual target values in X via `loc`.
target_vals = X.loc[[X.sub(n).abs().idxmin() 
                     for n in xrange(0, x[-1], spacer)]].tolist()  # `range` in Python 3.
>>> target_vals
[0, 32, 64, 97, 129]

# Sample the target values, taking a sample size of 1.
df[df['x'].isin(target_vals)].groupby('x').apply(lambda group: group.sample(1))

答案 1 :(得分:1)

您可以使用列表推导动态创建广告投放箱,然后使用pd.cut创建群组,并使用groupbysample(1)一起为每32个值' X&#获取一条记录39;

df = pd.DataFrame({'X':np.random.randint(0, 100, 5000),'Y':np.random.choice(list('ABCDEF'),5000)})

bins = [i for i in np.arange(df.X.min(), df.X.max(), 32)] + [np.inf]

df.groupby(pd.cut(df.X,bins=bins), as_index=False).apply(lambda x: x.sample(1).values)

输出:

[[15 'F']
 [51 'A']
 [90 'C']
 [98 'A']]