在python中,一个函数将根据另一行上的条件应用于一行中元素的组合

在python中,一个函数将根据另一行上的条件应用于一行中元素的组合,python,function,pandas,combinations,Python,Function,Pandas,Combinations,似乎也有类似的问题,但我找不到合适的答案。假设这是我的数据框,它对不同品牌的汽车有不同的观察结果: df = pandas.DataFrame({'Car' : ['BMW_1', 'BMW_2', 'BMW_3', 'WW_1','WW_2','Fiat_1', 'Fiat_2'], 'distance' : [10,25,22,24,37,33,49]}) 为简单起见,假设有一个函数,第一个元素乘以2,第二个元素乘以3: def my_fu

似乎也有类似的问题,但我找不到合适的答案。假设这是我的数据框,它对不同品牌的汽车有不同的观察结果:

df = pandas.DataFrame({'Car' : ['BMW_1', 'BMW_2', 'BMW_3', 'WW_1','WW_2','Fiat_1', 'Fiat_2'],
                       'distance'   : [10,25,22,24,37,33,49]})
为简单起见,假设有一个函数,第一个元素乘以2,第二个元素乘以3:

def my_func(x,y):
   z = 2x + 3y
   return z
我想得到汽车行驶距离的成对组合,并在我的函数中使用它们。但有两个条件,x和y不能是同一品牌,组合也不能重复。所需的输出如下:

  Car      Distance   Combinations                                
0  BMW_1   10         (BMW_1,WW_1),(BMW_1,WW_2),(BMW_1,Fiat_1),(BMW_1,Fiat_1)
1  BMW_2   25         (BMW_2,WW_1),(BMW_2,WW_2),(BMW_2,Fiat_1),(BMW_2,Fiat_1)
2  BMW_3   22         (BMW_3,WW_1),(BMW_3,WW_2),(BMW_3,Fiat_1),(BMW_3,Fiat_1)
3  WW_1    24         (WW_1, Fiat_1),(WW_1, Fiat_2)
4  WW_2    37         (WW_2, Fiat_1),(WW_2, Fiat_2)
5  Fiat_1  33         None
6  Fiat_2  49         None

//Output
[120, 134, 156, 178]
[113, 145, 134, 132]
[114, 123, 145, 182]
[153, 123] 
[120, 134] 
None 
None 
注:我为输出填写了数字

下一步,我想从每个品牌的“输出”行数组中获取最大数量。最终的数据应该是

  Car  Max_Distance
0 BMW  178
1 WW   153
2 Fiat None

如果有人能帮助我,我将不胜感激

i, j = np.tril_indices(len(df), 1)

def my_func(x,y):
    z = 2 * x + 3 * y
    return z

d = df.distance.values
c = df.Car.values
s = pd.Series(my_func(d[i], d[j]), [c[i], c[j]])

def test_name(df):
    name = df.index[0]
    n1, n2 = map(lambda x: x.split('_')[0], name)
    return n1 != n2

s.groupby(level=[0, 1]).filter(test_name).groupby(level=1).apply(list)

BMW_1       [78, 104, 96, 128]
BMW_2     [123, 149, 141, 173]
BMW_3     [114, 140, 132, 164]
Fiat_1                   [173]
WW_1           [116, 138, 170]
WW_2                [177, 209]
dtype: object
In [49]: x = pd.DataFrame(np.triu(squareform(pdist(df[['distance']], my_func))),
    ...:                  columns=df.Car.str.split('_').str[0],
    ...:                  index=df.Car.str.split('_').str[0]).replace(0, np.nan)
    ...:

In [50]: x[x.apply(lambda col: col.index != col.name)].max(1).max(level=0)
Out[50]:
Car
BMW     197.0
Fiat      NaN
WW      221.0
dtype: float64
旧答案:

In [49]: x = pd.DataFrame(np.triu(squareform(pdist(df[['distance']], my_func))),
    ...:                  columns=df.Car.str.split('_').str[0],
    ...:                  index=df.Car.str.split('_').str[0]).replace(0, np.nan)
    ...:

In [50]: x[x.apply(lambda col: col.index != col.name)].max(1).max(level=0)
Out[50]:
Car
BMW     197.0
Fiat      NaN
WW      221.0
dtype: float64
IIUC您可以执行以下操作:

from scipy.spatial.distance import pdist, squareform

def my_func(x,y):
    return 2*x + 3*y

x = pd.DataFrame(
    squareform(pdist(df[['distance']], my_func)),
    columns=df.Car.str.split('_').str[0],
    index=df.Car.str.split('_').str[0])
它产生了:

In [269]: x
Out[269]:
Car     BMW    BMW    BMW     WW     WW   Fiat   Fiat
Car
BMW     0.0   95.0   86.0   92.0  131.0  119.0  167.0
BMW    95.0    0.0  116.0  122.0  161.0  149.0  197.0
BMW    86.0  116.0    0.0  116.0  155.0  143.0  191.0
WW     92.0  122.0  116.0    0.0  159.0  147.0  195.0
WW    131.0  161.0  155.0  159.0    0.0  173.0  221.0
Fiat  119.0  149.0  143.0  147.0  173.0    0.0  213.0
Fiat  167.0  197.0  191.0  195.0  221.0  213.0    0.0
排除同一品牌:

In [270]: x.apply(lambda col: col.index != col.name)
Out[270]:
Car     BMW    BMW    BMW     WW     WW   Fiat   Fiat
Car
BMW   False  False  False   True   True   True   True
BMW   False  False  False   True   True   True   True
BMW   False  False  False   True   True   True   True
WW     True   True   True  False  False   True   True
WW     True   True   True  False  False   True   True
Fiat   True   True   True   True   True  False  False
Fiat   True   True   True   True   True  False  False

In [273]: x[x.apply(lambda col: col.index != col.name)]
Out[273]:
Car     BMW    BMW    BMW     WW     WW   Fiat   Fiat
Car
BMW     NaN    NaN    NaN   92.0  131.0  119.0  167.0
BMW     NaN    NaN    NaN  122.0  161.0  149.0  197.0
BMW     NaN    NaN    NaN  116.0  155.0  143.0  191.0
WW     92.0  122.0  116.0    NaN    NaN  147.0  195.0
WW    131.0  161.0  155.0    NaN    NaN  173.0  221.0
Fiat  119.0  149.0  143.0  147.0  173.0    NaN    NaN
Fiat  167.0  197.0  191.0  195.0  221.0    NaN    NaN
选择每行的最大值:

In [271]: x[x.apply(lambda col: col.index != col.name)].max(1)
Out[271]:
Car
BMW     167.0
BMW     197.0
BMW     191.0
WW      195.0
WW      221.0
Fiat    173.0
Fiat    221.0
dtype: float64
每个品牌的最大值:

In [276]: x[x.apply(lambda col: col.index != col.name)].max(1).max(level=0)
Out[276]:
Car
BMW     197.0
Fiat    221.0
WW      221.0
dtype: float64

我只是想说清楚。。。你不想将任何宝马与任何其他宝马进行比较吗?是的,没错,只是与不同的品牌进行比较?给定z=2x+3y:bmw_菲亚特2*25+3*49与菲亚特+bmw 2*49+3*25不同。不,在实际功能中这并不重要,它可能类似于x+y。我只想按第一个元素分组哦,也许我不够清楚,对不起,我也不想让WW和菲亚特与它们自己的类型相匹配:(非常感谢你的回答。如果我必须将其应用于一个大型csv文件,它会很有效?@edyvedy13,在你尝试之前你永远不会知道;-)我就快到了,但唯一的一点是,它应该是元素的组合,当我得到宝马的结果时,我不想再将WW与宝马进行比较。然后,我想将WW与菲亚特进行比较,菲亚特基本上什么都没有。我甚至愿意为它付费,如果有人能解决我的问题,因为我正在为它工作4天:/,对不起,我刚刚看到它,如果我们考虑组合和groupby函数,当我们说groupby第一个元素时,应该没有什么留给Fiat了。它有点复杂:/