根据索引和列将函数应用于数据框中的每个单元格

Applying function to every cell in a Dataframe based on index and col

我有一个 pandas 数据框,其格式与 and I'm trying to achieve the same result. In my case, I am calculating the fuzz-ratio 中行索引和对应列之间的格式完全相同。

如果我尝试此代码(基于对链接问题的回答)

def get_similarities(x):
    return x.index + x.name

test_df = test_df.apply(get_similarities)

行索引和列名称的连接按单元格方式发生,正如预期的那样。 运行 type(test_df) returns pandas.core.frame.DataFrame,符合预期。

但是,如果我像这样调整代码以适应我的场景

def get_similarities(x):
    return fuzz.partial_ratio(x.index, x.name)

test_df = test_df.apply(get_similarities)

没用。我取回了一个系列,而不是数据框(该函数的 return 类型是 int

我不明白为什么这两个样本的行为不一样,也不明白如何修复我的代码,所以它 return 是一个数据框,行索引之间的每个单元格 fuzzy.ratio该单元格的名称和该单元格的列名称。

下面的方法呢?

假设我们有两组字符串:

In [245]: set1
Out[245]: ['car', 'bike', 'sidewalk', 'eatery']

In [246]: set2
Out[246]: ['walking', 'caring', 'biking', 'eating']

解决方案:

In [247]: from itertools import product

In [248]: res = np.array([fuzz.partial_ratio(*tup) for tup in product(set1, set2)])

In [249]: res = pd.DataFrame(res.reshape(len(set1), -1), index=set1, columns=set2)

In [250]: res
Out[250]:
          walking  caring  biking  eating
car            33     100       0      33
bike           25      25      75      25
sidewalk       73      20      22      36
eatery         17      33       0      50

花了一些时间,但我想通了。问题来自这样一个事实,即 DataFrame.apply 要么按列应用,要么按行应用,而不是逐个单元格应用。因此,您的 get_similarities 函数实际上是一次访问整行或整列数据!默认情况下,它会获取整个列 - 因此要解决您的问题,您只需创建一个 returns 列表的 get_similarities 函数,您可以在其中手动调用每个元素的 fuzz.partial_ratio ,就像这样:

import pandas as pd 
from fuzzywuzzy import fuzz

def get_similarities(x):

    l = []
    for rname in x.index:
        print "Getting ratio for %s and %s" % (rname, x.name)
        score = fuzz.partial_ratio(rname,x.name)
        print "Score %s" % score
        l.append(score)

    print len(l)
    print
    return l



a = pd.DataFrame([[1,2],[3,4]],index=['apple','banana'], columns=['aple','banada'])
c = a.apply(get_similarities,axis=0)

print c
print type(c)

我将我的打印语句留在了它们中,这样您就可以看到 DataFrame.apply 调用为您自己做了什么 -- 那就是它为我点击的时候。

有一种方法可以通过 DataFrame.apply 和一些行操作来完成此操作。

假设'test_df`如下:

In [73]: test_df
Out[73]: 
                  walking          caring          biking          eating
car            carwalking       carcaring       carbiking       careating
bike          bikewalking      bikecaring      bikebiking      bikeeating
sidewalk  sidewalkwalking  sidewalkcaring  sidewalkbiking  sidewalkeating
eatery      eaterywalking    eaterycaring    eaterybiking    eateryeating

In [74]: def get_ratio(row):
    ...:     return row.index.to_series().apply(lambda x: fuzz.partial_ratio(x, 
    ...: row.name))
    ...: 

In [75]: test_df.apply(get_ratio)
Out[75]: 
          walking  caring  biking  eating
car            33     100       0      33
bike           25      25      75      25
sidewalk       73      20      22      36
eatery         17      33       0      50