我正在寻找创建一个函数,该函数计算数据集中所选类别与所有其他类别之间的曼哈顿距离。然后,该函数应返回与所选内容距离最近的类别。
df = pd.DataFrame(np.random.randint(0,100, size= (10,4)), columns=list('ABCD'))
df['category']= ['apple','orange','grape','berry','strawberry','banana','kiwi','lemon','lime','pear']
下面的代码返回最小的4个距离,其中包括选定的类别(距离= 0;这是多余的,不需要的)。我需要代码仅返回最低的3个距离作为类别列表,第一个是最小的距离。
def distance(row):
cols = list('ABCD')
return (df[cols] - row[cols]).abs().sum(axis=1)
df.set_index('category', inplace=True)
dist = df.apply(distance, axis=1)
dist['apple'].nsmallest(4)
例如,如果选择了“ Apple”,并且距苹果的三个最低距离是Berry,Orange和Grape,则返回应该像这样:[“ Berry”,“ Orange”,“ Grape”]
答案 0 :(得分:1)
设置:
df = pd.DataFrame(np.random.randint(0,100, size= (10,4)), columns=list('ABCD'))
df['category']= . ['apple','orange','grape','berry','strawberry','banana','kiwi','lemon','lime','pear']
df.set_index('category', inplace = True)
这是一口,但是:
lowest_3 = [df.index[pd.Series([abs(df.loc[ind1] - df.loc[ind2]).sum() for ind2 in df.index]).argsort()[1:4]].tolist() for ind1 in df.index]
lowest_3_series = pd.Series(lowest_3, index = df.index)
lowest_3_series['apple'] = ['banana', 'lemon', 'grape'] # Results will differ due to randomness obviously
这将为您提供df.index中每个值的最低3个值的列表。
例如,此列表的第一个元素是您对'apple'
的解决方案
说明:
首先,为df.index中的每个索引创建列表推导。嵌套列表推导再次是df.index的迭代。您为此索引调用df,并将它们成对比较(总计n ^ 2个比较)。您可以通过取每个列值之间的绝对值并将它们相加来比较每个索引。然后将此列表变成一系列,并使用argsort
获取前3个(不包括始终为0的自反比较)。然后,在该索引片上调用df.index,这将为您提供这3个最低值的名称。
答案 1 :(得分:0)
一种选择是使用scipy.spatial.distance
中的函数cityblock
:
from scipy.spatial import distance
df.set_index('category', inplace = True)
>> df.apply(lambda x: distance.cityblock(x, df.loc['apple',:]), axis=1
).drop('apple', axis=1).nsmallest(4).index.values.tolist()
['strawberry', 'berry', 'kiwi', 'orange']
基本上,您会获得从每一行到选定行之间的距离。然后,删除包含所选标签的行,并选择最小距离的索引。