Python 在dataframe列中查找字典的值并修改它

Python 在dataframe列中查找字典的值并修改它,python,pandas,dictionary,dataframe,any,Python,Pandas,Dictionary,Dataframe,Any,我现在正在处理数据帧和字典,我有一个问题, 我有一本字典“水果” 和一个数据帧——“股票”: 我想做下一件事: 用Fruits.values()替换库存['Fruit']中的所有值,方法如下: 如果来自水果的值出现在Stock['Fruit']行中,它将以以下方式替换: Fruit Price 0 Sweet Mango 1 1 Green Apple 2 2 Banana 0 3 Ban

我现在正在处理数据帧和字典,我有一个问题, 我有一本字典“水果”

和一个数据帧——“股票”:

我想做下一件事: 用
Fruits.values()
替换库存['Fruit']中的所有值,方法如下: 如果来自水果的值出现在
Stock['Fruit']
行中,它将以以下方式替换:

   Fruit             Price
0  Sweet Mango           1
1  Green Apple           2
2  Banana                0
3  Banana                5
很少有蓝色的香蕉-->香蕉

黑色香蕉-->香蕉

现在,DataFrame库存将如下所示:

   Fruit             Price
0  Sweet Mango           1
1  Green Apple           2
2  Banana                0
3  Banana                5
我找到了不同的代码来替换或检查数据帧中是否出现了来自dictionary的值

Stock['Fruit'] = Stock.Fruit.map(Fruits)

if (Fruits.values() in Stock['Fruit'] for item in Stock)

any('Mango' in Stock['Fruit'] for index,item in Stock.iterrows())

但是我找不到任何东西来更新数据框的行,您可以使用带有自定义函数的
apply()

Stock['Fruit'] = Stock.Fruit.map(Fruits)

if (Fruits.values() in Stock['Fruit'] for item in Stock)

any('Mango' in Stock['Fruit'] for index,item in Stock.iterrows())
import pandas as pd

df = pd.DataFrame([['Sweet Mango', 1],['Green Apple', 2],['Few blue Banana', 0],['Black Banana', 5]],
  columns=['Fruit','Price'])

fruits = {'BN':'Banana', 'LM': 'Lemon', 'AP':'Apple', 'MG': 'Mango'}

def find_category(x):

  return [k for k in fruits.values() if k in x][0]

df['Fruit'] = df['Fruit'].apply(find_category)
收益率:

    Fruit  Price
0   Mango      1
1   Apple      2
2  Banana      0
3  Banana      5

IIUC,您可以将
apply()
与自定义函数一起使用:

import pandas as pd

df = pd.DataFrame([['Sweet Mango', 1],['Green Apple', 2],['Few blue Banana', 0],['Black Banana', 5]],
  columns=['Fruit','Price'])

fruits = {'BN':'Banana', 'LM': 'Lemon', 'AP':'Apple', 'MG': 'Mango'}

def find_category(x):

  return [k for k in fruits.values() if k in x][0]

df['Fruit'] = df['Fruit'].apply(find_category)
收益率:

    Fruit  Price
0   Mango      1
1   Apple      2
2  Banana      0
3  Banana      5

对条件和提取所需值使用字符串方法

pat = r'({})'.format('|'.join(d.values()))
cond = df['Fruit'].str.contains('|'.join(d.values()))
df.loc[cond, 'Fruit'] = df['Fruit'].str.extract((pat), expand = False)

    Fruit       Price
0   Sweet Mango 1
1   Apple       2
2   Banana      0
3   Banana      5
编辑:正如@user3483203所建议的,一旦提取模式,您就可以用原始值填充缺少的值

df['Fruit'] = df['Fruit'].str.extract(pat).fillna(df.Fruit)

对条件和提取所需值使用字符串方法

pat = r'({})'.format('|'.join(d.values()))
cond = df['Fruit'].str.contains('|'.join(d.values()))
df.loc[cond, 'Fruit'] = df['Fruit'].str.extract((pat), expand = False)

    Fruit       Price
0   Sweet Mango 1
1   Apple       2
2   Banana      0
3   Banana      5
编辑:正如@user3483203所建议的,一旦提取模式,您就可以用原始值填充缺少的值

df['Fruit'] = df['Fruit'].str.extract(pat).fillna(df.Fruit)

使用答案的结果,我们创建了一个新类,该类子类为
defaultdict
,并覆盖其
\uuuuuu missing\uuuuu
属性,以允许将密钥传递到
默认工厂

from collections import defaultdict
class keydefaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key)
        else:
            ret = self[key] = self.default_factory(key)
            return ret
我们创建了一个初始字典,用于映射要替换的
'Fruits'
列中的2个值

fruit_dict = {'Few blue Banana': 'Banana', 'Black Banana': 'Banana'}
然后我们用
lambda x:x
default\u工厂创建一个类的新实例。也就是说,如果我们在搜索时找不到该键,请将该键作为值输入

fruit_col_map = keydefaultdict(lambda x: x)
fruit_col_map.update(**fruit_dict)
最后,更新列:

df['Fruit'] = df['Fruit'].map(fruit_col_map)
df
输出:

         Fruit  Price
0  Sweet Mango      1
1  Green Apple      2
2       Banana      0
3       Banana      5
与公认的答案相比,这要快6倍多:

df = pd.DataFrame({
    'Fruit': ['Sweet Mango', 'Green Apple', 'Few blue Banana', 'Black Banana']*1000,
    'Price': [1, 2, 0, 5]*1000
})
%timeit df['Fruit'].map(fruit_col_map)
结果:

1.03 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.85 ms ± 223 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
接受的答复:

pat = r'({})'.format('|'.join(fruit_dict.values()))
%timeit df['Fruit'].str.extract(pat).fillna(df['Fruit'])
结果:

1.03 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.85 ms ± 223 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用答案的结果,我们创建了一个新类,该类子类为
defaultdict
,并覆盖其
\uuuuuu missing\uuuuu
属性,以允许将密钥传递到
默认工厂

from collections import defaultdict
class keydefaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key)
        else:
            ret = self[key] = self.default_factory(key)
            return ret
我们创建了一个初始字典,用于映射要替换的
'Fruits'
列中的2个值

fruit_dict = {'Few blue Banana': 'Banana', 'Black Banana': 'Banana'}
然后我们用
lambda x:x
default\u工厂创建一个类的新实例。也就是说,如果我们在搜索时找不到该键,请将该键作为值输入

fruit_col_map = keydefaultdict(lambda x: x)
fruit_col_map.update(**fruit_dict)
最后,更新列:

df['Fruit'] = df['Fruit'].map(fruit_col_map)
df
输出:

         Fruit  Price
0  Sweet Mango      1
1  Green Apple      2
2       Banana      0
3       Banana      5
与公认的答案相比,这要快6倍多:

df = pd.DataFrame({
    'Fruit': ['Sweet Mango', 'Green Apple', 'Few blue Banana', 'Black Banana']*1000,
    'Price': [1, 2, 0, 5]*1000
})
%timeit df['Fruit'].map(fruit_col_map)
结果:

1.03 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.85 ms ± 223 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
接受的答复:

pat = r'({})'.format('|'.join(fruit_dict.values()))
%timeit df['Fruit'].str.extract(pat).fillna(df['Fruit'])
结果:

1.03 ms ± 48.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.85 ms ± 223 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


为什么
绿苹果
没有被
苹果
取代?我刚才举了一个我想要的例子,我问你为什么不把
绿苹果
改成
苹果
,但是你把
黑香蕉
改成
香蕉
,在你的输出上面,我的答案包括你想要的输出吗?如果没有,你能澄清你想要的完整输出是什么吗?
Green Apple
为什么没有被
Apple
取代?我只是举了一个我想要的例子,我想问你为什么不把
Green Apple
改成
Apple
,但是您确实在上面的输出中将
黑香蕉
更改为
香蕉
,我的答案是否包括您想要的输出?如果没有,你能澄清你想要的完整输出是什么吗?或者干脆
df.Fruit.str.extract(pat).fillna(df.Fruit)
。您也不需要指定
expand=False
,因为您只有一个捕获组,或者只有
df.Fruit.str.extract(pat).fillna(df.Fruit)
。您也不需要指定
expand=False
,因为您只有一个捕获组,如果处理较大的数据帧,“apply()”将是最有效的。@rahlf23 tnx,它适用于我作为示例提供的数据帧和字典,现在我尝试用另一个来实现这一点,还有一个问题:新字典
states={'OH':'OH':'KY':'Kentucky','AS':'American Samoa','NV':'Nevada'…}
和一个列为'State and Region'的数据框。State也包含了一些我想用一个词替换的词。当我复制了你的代码并只更改了变量时,它给了我一个错误:
--->5返回[k代表k在states.values()如果k在x][0]索引器:列表索引超出范围
当我删除
[0]
@rahlf23当我删除
[0]
时,它给了我一个“良好”的数据帧,但接下来的问题是:`State RegionName 0[]奥本1[阿拉巴马州]佛罗伦萨2[]杰克逊维尔3[阿拉巴马州]利文斯顿4[]蒙特瓦洛5[]特洛伊6[阿拉巴马州]塔斯卡卢萨7[]塔斯基吉8[阿拉斯加州]费尔班克斯9[亚利桑那州]弗拉格斯塔夫`正如你所见,它跳过了一些值,并添加了“[]”全体others@JLuxton我使用的那个要大得多,我只是用小的=)@B.Kristina练习过。如果字典中的值没有精确匹配,这个解决方案将返回
[]
。使用
[0]
的原因是返回第一个匹配(因为我假设您的值是唯一的,并且对多个键无效)。如果删除
[0]
,则它将返回包含该值的键列表。'apply()“如果处理更大的数据帧,将是最有效的。@rahlf23 tnx,它适用于我给出的数据帧和字典作为示例,现在我尝试使用另一个字典,但有一个问题:新字典
states={'OH':'oho','KY':'Kentucky','as':'American Samoa','NV':'Nevada'…}
和列为“State and Region”的数据帧状态中也包含一些我想用一个词替换的词。当我复制了你的代码,只更改了变量时,它给了我一个错误:
--->5返回[k代表状态中的k