返回列,提供匹配值的平均值

时间:2016-12-03 22:49:55

标签: python pandas

以下代码允许我查找匹配值:

var a = function (callback) {
        for (var eachRow = 0; eachRow < 20; eachRow++) {
            for (var eachCol = 0; eachCol < 20; eachCol++) {
                callback(array, eachRow, eachCol);
            }
        }
    };

a(function (array, x, y) {
    if (array[x][y]){
        //do something
    }
});

有关此内容的信息可以在here找到:

更好的解释来自@Andras Deak

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)) 中的生成器表达式遍历每个列对,并构造相应的布尔向量。这些对每个列对求和,并将结果列附加到数据帧”。

thresh = 0.3的示例输出:

sum()

如何返回另一列 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']&amp;的平均值。 0.146360。我希望这使用与原始代码相同的-0.099707逻辑,因为这可以很好地扩展到我的实际数据。

1 个答案:

答案 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)

也就是说,如果这些值比thresh更接近,它将给出给定列对的元素的总和,否则我们得到0.对于所有3个组合,我们得到一个具有零或两个和的数组-elements值,我们再次总结。如果有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