我感兴趣的是将1个dataframe列中的所有值与第2列中的所有值进行比较,然后生成列表或子集df,其值来自与第1列匹配的第3列的值。希望这个例子能更好地解释它:
有关简化示例,请说我生成以下pandas数据帧:
fake_df=pd.DataFrame({'m':[100,120,101,200,201,501,350,420,525,500],
'n':[10.0,11.0,10.2,1.0,2.0,1.1,3.0,1.0,2.0,1.0],
'mod':[101.001,121.001,102.001,201.001,202.001,502.001,351.001,421.001,526.001,501.001]})
print fake_df
我感兴趣的是找到列'm'中的所有值都在0.1的任何值之内 列'mod'并返回列'n'中与列'm'命中对应的值。因此,对于上面的代码,返回将是: 10.2,2.0,1.1 (因为101,201和501在'mod'栏中都有接近的命中率。)
我找到了在同一行进行比较的方法,但不像上面那样。有没有办法在没有大量循环的熊猫中做到这一点? 谢谢!
答案 0 :(得分:2)
我不会在熊猫中知道这种方法,但是当你将范围扩大到包括在内时 numpy,脑海中浮现出两种选择。
如果你可以忍受N ** 2内存开销,你可以进行numpy广播 找出所有"相邻"元素一步到位:
In [25]: fake_df=pd.DataFrame({'m':[100,120,101,200,201,501,350,420,525,500],
'n':[10.0,11.0,10.2,1.0,2.0,1.1,3.0,1.0,2.0,1.0],
'mod':[101.001,121.001,102.001,201.001,202.001,502.001,351.001,421.001,526.001,501.001]})
In [26]: mvals = fake_df['m'].values
In [27]: modvals = fake_df['mod'].values
In [28]: is_close = np.abs(mvals - modvals[:, np.newaxis]) <= 0.1; is_close.astype(int)
Out[28]:
array([[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0]])
因为我们只关心&#39; mod&#39;具有相邻&#39; s的值,在轴上聚合= 0:
In [29]: is_close.any(axis=0).astype(int)
Out[29]: array([0, 0, 1, 0, 1, 1, 0, 0, 0, 0])
或其他
In [30]: fake_df.ix[is_close.any(axis=0), 'n']
Out[30]:
2 10.2
4 2.0
5 1.1
Name: n, dtype: float64
在没有任何散列/舍入的情况下查找小于O(N ** 2)的相邻元素 技巧,你必须做一些排序:
In [103]: modvals_sorted = np.sort(modvals)
In [104]: next_indices = np.searchsorted(modvals_sorted, mvals)
您有下一个元素的索引,但它们可能超出原始元素
数组,所以最后需要一个额外的NaN
以避免IndexError
。相同
逻辑适用于next_indices - 1
以前的元素:要避免
在第一个元素之前建立索引,我们也必须预先添加一个NaN
。请注意出现的+ 1
,因为NaN
之一已添加到开头。
In [105]: modvals_sorted_plus = np.r_[np.nan, modvals_sorted, np.nan]
In [106]: nexts = modvals_sorted_plus[next_indices + 1]
In [107]: prevs = modvals_sorted_plus[(next_indices - 1) + 1]
现在它是微不足道的。请注意,我们已经有prevs <= mvals <= nexts
,所以我们
不需要使用np.abs
。此外,所有缺失的元素都是NaN
,并与它们进行比较,结果False
不会改变any
操作的结果。
In [108]: adjacent = np.c_[prevs, mvals, nexts]; adjacent
Out[108]:
array([[ nan, 100. , 101.001],
[ 102.001, 120. , 121.001],
[ nan, 101. , 101.001],
[ 121.001, 200. , 201.001],
[ 121.001, 201. , 201.001],
[ 421.001, 501. , 501.001],
[ 202.001, 350. , 351.001],
[ 351.001, 420. , 421.001],
[ 502.001, 525. , 526.001],
[ 421.001, 500. , 501.001]])
In [109]: (np.diff(adjacent, axis=1) <= 0.1).any(axis=1)
Out[109]: array([False, False, True, False, True, True, False, False, False, False], dtype=bool)
In [110]: mask = (np.diff(adjacent, axis=1) <= 0.1).any(axis=1)
In [112]: fake_df.ix[mask, 'n']
Out[112]:
2 10.2
4 2.0
5 1.1
Name: n, dtype: float64
答案 1 :(得分:1)
尝试以下方法:
# I assume all arrays involved to be or to be converted to numpy arrays
import numpy as np
m = np.array([100,120,101,200,201,501,350,420,525,500])
n = np.array([10.0,11.0,10.2,1.0,2.0,1.1,3.0,1.0,2.0,1.0])
mod = np.array([101.001,121.001,102.001,201.001,202.001,502.001,351.001,421.001,526.001,501.001])
res = []
# for each entry in mod, look in m for "close" values
for i in range(len(mod)):
# for each hit, store entry from n in result list
res.extend(n[np.fabs(mod[i]-m)<=0.1])
# cast result to numpy array
res = np.array(res)
print res
输出
[ 10.2 2. 1.1]
答案 2 :(得分:1)
我将制作numpy(导入为np),大熊猫在引擎盖下使用。 np.isclose返回一个布尔索引器:对于iterable的每个值,对应于值True
的{{1}}或False
值在每个值的m
范围内atol
。
df["mod"]
使用您提供的DataFrame产生输出:
>>> for i, m in df["m"].iteritems():
... indices = np.isclose(m, df["mod"], atol=0.1)
... if any(indices):
... print df["n"][i]