2016-12-03 69 views
0

下面的代码可以让我找到匹配的值:返回塔提供匹配值的平均值

from itertools import combinations 
df = pd.DataFrame(np.random.randn(12, 3), columns=['A', 'B', 'C']) 
thresh = .3 
df['matches'] = sum(abs(df[k1]-df[k2])<thresh for k1,k2 in combinations(df.keys(),2)) 

信息关于这个可以发现here

更好的解释是从@Andras迪克

sum()中的生成器表达式循环遍历每个列对,并构造相应的布尔向量。对每个列对求和,并将结果列附加到数据帧“。

实施例输出脱粒= 0.3:

  A   B   C matches 
0 0.146360 -0.099707 0.633632  1 
1 1.462810 -0.186317 -1.411988  0 
2 0.358827 -0.758619 0.038329  0 
3 0.077122 -0.213856 -0.619768  1 
4 0.215555 1.930888 -0.488517  0 
5 -0.946557 -0.904743 -0.004738  1 
6 -0.080209 -0.850830 -0.866865  1 
7 -0.997710 -0.580679 -2.231168  0 
8 1.762313 -0.356464 -1.813028  0 
9 1.151338 0.347636 -1.323791  0 
10 0.248432 1.265484 0.048484  1 
11 0.559934 -0.401059 0.863616  0 

我怎样才能返回另一个柱df['matches_mean']提供具有匹配的值的平均值?因此,对于上面示例中的第一行,将返回平均值0.146360 & -0.099707。我希望使用与原始代码相同的itertools combinations逻辑,因为这可以很好地适应我的真实数据。

+0

如果多于一对列的接近什么?该专栏应包含哪些内容? –

+0

你好安德拉斯。我最终寻找大多数比赛以及这场比赛的平均数。所以如果3列匹配并且2匹配来自同一行,那么3列的平均值将是理想的。谢谢你的帮助! – ade1e

+0

那么没有匹配的行呢? –

回答

1

暂时这里是一个几乎完美的解决方案。问题是,当你想计算多个匹配的平均值(比如说,一行中的所有三个数字都接近阈值)时,你需要在计算平均值时取适当数量的值。如果3列中只有1或3个匹配,这很容易。但是,当两对数字“接近”但第三对不是时,下面的代码将会出现错误。

这个想法是总结每行和每个组合的匹配值。例如,如果只有行'A''B'“接近”(在阈值内),我们得到df.A+df.B,其必须除以2以得到平均值。当所有三个“接近”时,我们得到2*df.A + 2*df.B + 2*df.C,其可以被6除以得到适当的平均值。但是,在第三种情况下,例如,我们得到df.A + 2*df.B + df.C(当A和B接近时,B和C接近,但A和C不接近)。在这种情况下,我们不能用任何东西来划分,以获得适当的意思。我们可能应该用4除以得到“大约一个”元素的错误含义。我的观点是,如果我们要妥善处理这种情况,那么代码会复杂得多,根据您的需要,这可能不值得。目前还不清楚你要如何处理这个案件。当前版本除以4,相当于平均A与B,平均B与C,然后再次平均这些平均值。

所以这里有云:

import numpy as np 
import pandas as pd 
from itertools import combinations 

colnames = ['A', 'B', 'C'] 
df = pd.DataFrame(np.random.randn(12, 3), columns=colnames) 
thresh = .3 
df['matches'] = sum(abs(df[k1]-df[k2])<thresh 
        for k1,k2 in combinations(colnames,2)) 
# this is your starting point, we'll need df['matches'] too 

tmpsums = sum(np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0) 
       for k1,k2 in combinations(colnames,2)) 
# divide by 2/4/6: 
df['matches_mean'] = np.where(df['matches'],tmpsums/df['matches']/2,0) 

在发电机表达的出现总和达到口感好等限制,我承认。你可能想把它写在适当的for循环中,但是你必须递增地总结tmpsums中的值。我承认这可能更漂亮。

无论如何,这第二个生成器表达式的工作方式与第一个类似。该产生价值当然是不同的,它是

np.where(abs(df[k1]-df[k2])<thresh,df[k1]+df[k2],0) 

也就是说,它会给我们给定的列对,如果这些值比脱粒接近的元素的总和,否则我们得到0。对于所有3组合我们得到一个具有这样的零或者两个和的元素值的数组,并且我们再次总结它们。在有0个匹配的情况下,我们得到0.如果有1个匹配,我们总结两个匹配元素。对于2场比赛,我们得到了前面提到的混合总和,并且在3场比赛中我们有两次所有术语。

剩下的是将非零例除以匹配的数量,这只是一个分割,其中我们已经知道的匹配数量是两倍(但我们必须注意零除)。

实施例输出与thresh = 0.3

  A   B   C matches matches_mean 
0 0.716278 0.681279 0.861410  3  0.752989 
1 -0.109029 -0.646952 0.268038  0  0.000000 
2 -1.095221 -1.088397 1.100645  1  -1.091809 
3 -1.970372 -0.367096 -0.337098  1  -0.352097 
4 -1.030003 0.082001 -0.807431  1  -0.918717 
5 1.660611 -0.046429 0.557107  0  0.000000 
6 -0.508715 -0.588217 0.014917  1  -0.548466 
7 0.578028 -0.187097 -0.420243  1  -0.303670 
8 0.233687 1.311917 1.888947  0  0.000000 
9 0.478863 1.087957 -0.897025  0  0.000000 
10 -0.001462 0.866320 -1.198642  0  0.000000 
11 0.297946 0.564325 -1.098887  1  0.431135 
+0

谢谢@Andras迪克这是伟大的。我已标记为完整,但会再提出一个问题。无论如何要添加显示匹配模式的另一列,即如果所有匹配都在阈值内,则显示“df.A/df.B/df.C”的字符串。或者对于更大的数据集,如果在同一行上的不同匹配显示,即如果看到两个单独的匹配组,则显示“df.A/df.B/df.C” - “df.D/df.L/df.Z” 。我不知道这是否可以做到诚实。 – ade1e

+0

@adele谢谢。这绝对是可行的,它只需要更多的工作:)如果你想构建这样的字符串,我不认为这将以矢量化的方式工作。这意味着你可能不得不循环你的行,这不能很好地扩展。所以,假设你的意思是如果它可以有效地做到这一点:我不这么认为:( –