如何在pandas表中的一次迭代中设置多个值?

时间:2017-03-14 21:46:26

标签: python python-3.x pandas

我正在使用itertuples()迭代器函数迭代pandas表。当条件为True时,我想在另一列中设置一个值。这很简单。但是我想再次根据先前设置的值将另一个值设置为另一列,这样就不起作用了。我必须第二次做到这一点,但这是低效的。 如何在一个迭代过程中在不同的列中设置多个值。

以下是一些示例代码:

data = {
'Animal': ['cat', 'dog', 'dog', 'cat', 'bird', 'dog', 'cow'],
'Noise': ['muh', 'miau', 'wuff', 'piep', 'piep', 'miau', 'muh']
}

df = pd.DataFrame(data)
df.insert(loc=2, column='Match', value='')
df.insert(loc=3, column='Comment', value='')
for row in df.itertuples():
    if row.Animal == 'cat' and row.Noise == 'miau':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'dog' and row.Noise == 'wuff':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'bird' and row.Noise == 'piep':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'cow' and row.Noise == 'muh':
        df.set_value(index=row.Index, col='Match', value=True)

    # Why is this not getting applied to the 'Comment' column?
    if row.Match is True:
        df.set_value(index=row.Index, col='Comment', value='yeah')

我必须做另一次迭代而不是填充Comment-column:

for row in df.itertuples():
    if row.Match is True:
        df.set_value(index=row.Index, col='Comment', value='yeah')

但是,即使用500000+值,这也非常低效且耗时。 那么做什么更好的方法呢?

2 个答案:

答案 0 :(得分:1)

考虑您的df

data = {
'Animal': ['cat', 'dog', 'dog', 'cat', 'bird', 'dog', 'cow'],
'Noise': ['muh', 'miau', 'wuff', 'piep', 'piep', 'miau', 'muh']
}

df = pd.DataFrame(data)

我使用最初计算的字典来定义匹配的内容。然后,使用map转换并测试相等性。之后,我会使用assign生成所需的列。

matches = dict(cat='miau', dog='wuff', bird='piep', cow='muh')

match = df.Animal.map(matches) == df.Noise

df.assign(Match=match, Comment=np.where(match, 'yeah', ''))

  Animal Noise  Match Comment
0    cat   muh  False        
1    dog  miau  False        
2    dog  wuff   True    yeah
3    cat  piep  False        
4   bird  piep   True    yeah
5    dog  miau  False        
6    cow   muh   True    yeah

回答您的具体问题:
循环中的row不再附加到数据框。因此,当您使用TrueFalseset_value分配给数据框时,您将无法访问刚刚从row设置的值。相反,请使用df.get_value

for row in df.itertuples():
    if row.Animal == 'cat' and row.Noise == 'miau':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'dog' and row.Noise == 'wuff':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'bird' and row.Noise == 'piep':
        df.set_value(index=row.Index, col='Match', value=True)
    elif row.Animal == 'cow' and row.Noise == 'muh':
        df.set_value(index=row.Index, col='Match', value=True)

    # This should work
    if df.get_value(index=row.Index, col='Match') is True:
        df.set_value(index=row.Index, col='Comment', value='yeah')

答案 1 :(得分:0)

而不是

 # Why is this not getting applied to the 'Comment' column?
    if row.Match is True:
        df.set_value(index=row.Index, col='Comment', value='yeah')

你可以在for循环之后使用它。

df['Comment'] = df['Match'].apply(lambda x: 'yeah' if x == True else '')