Обновить значения строк, в которых выполняется определенное условие в пандах

96

Скажем, у меня есть следующий фрейм данных:

Таблица

Каков наиболее эффективный способ обновить значения столбцов feat и another_feat, где поток имеет номер 2 ?

Это все?

for index, row in df.iterrows():
    if df1.loc[index,'stream'] == 2:
       # do something

ОБНОВЛЕНИЕ: что делать, если у меня более 100 столбцов? Я не хочу явно называть столбцы, которые хочу обновить. Я хочу разделить значение каждого столбца на 2 (кроме столбца потока).

Итак, чтобы было ясно, какова моя цель:

Разделение всех значений на 2 из всех строк, имеющих поток 2, но без изменения столбца потока

Станко
источник

Ответы:

199

Я думаю, вы можете использовать, locесли вам нужно обновить два столбца до одинакового значения:

df1.loc[df1['stream'] == 2, ['feat','another_feat']] = 'aaaa'
print df1
   stream        feat another_feat
a       1  some_value   some_value
b       2        aaaa         aaaa
c       2        aaaa         aaaa
d       3  some_value   some_value

Если вам нужно обновление отдельно, можно использовать один из вариантов:

df1.loc[df1['stream'] == 2, 'feat'] = 10
print df1
   stream        feat another_feat
a       1  some_value   some_value
b       2          10   some_value
c       2          10   some_value
d       3  some_value   some_value

Другой распространенный вариант - использование numpy.where:

df1['feat'] = np.where(df1['stream'] == 2, 10,20)
print df1
   stream  feat another_feat
a       1    20   some_value
b       2    10   some_value
c       2    10   some_value
d       3    20   some_value

РЕДАКТИРОВАТЬ: Если вам нужно разделить все столбцы без streamусловия True, используйте:

print df1
   stream  feat  another_feat
a       1     4             5
b       2     4             5
c       2     2             9
d       3     1             7

#filter columns all without stream
cols = [col for col in df1.columns if col != 'stream']
print cols
['feat', 'another_feat']

df1.loc[df1['stream'] == 2, cols ] = df1 / 2
print df1
   stream  feat  another_feat
a       1   4.0           5.0
b       2   2.0           2.5
c       2   1.0           4.5
d       3   1.0           7.0
Jezrael
источник
Я обновил свой вопрос, у меня более 100 столбцов, как мне это сделать?
Станко
1
@Stanko - я думаю, это другой вопрос - вам нужно как-то выделить эти 100столбцы. например, если нужны 100первые столбцы, используйте, df.columns[:100]а затем переходите к loc.
jezrael
Мне не обязательно нужны первые 100 столбцов, я просто хочу разделить все значения столбцов (кроме столбца потока) на 2, где поток равен fe 2
Станко
поэтому разница между loc и np. где то, что loc изменяет строки, которые удовлетворяют только условию, но np.where имеет оператор if и else, поэтому он изменит все строки?
Амблеу,
1
@Ambleu - точно.
Джезраэль
3

Вы можете сделать то же самое .ix, например:

In [1]: df = pd.DataFrame(np.random.randn(5,4), columns=list('abcd'))

In [2]: df
Out[2]: 
          a         b         c         d
0 -0.323772  0.839542  0.173414 -1.341793
1 -1.001287  0.676910  0.465536  0.229544
2  0.963484 -0.905302 -0.435821  1.934512
3  0.266113 -0.034305 -0.110272 -0.720599
4 -0.522134 -0.913792  1.862832  0.314315

In [3]: df.ix[df.a>0, ['b','c']] = 0

In [4]: df
Out[4]: 
          a         b         c         d
0 -0.323772  0.839542  0.173414 -1.341793
1 -1.001287  0.676910  0.465536  0.229544
2  0.963484  0.000000  0.000000  1.934512
3  0.266113  0.000000  0.000000 -0.720599
4 -0.522134 -0.913792  1.862832  0.314315

РЕДАКТИРОВАТЬ

После дополнительной информации все столбцы, при соблюдении некоторых условий, будут возвращены с уменьшенными вдвое значениями:

>> condition = df.a > 0
>> df[condition][[i for i in df.columns.values if i not in ['a']]].apply(lambda x: x/2)

Надеюсь, это поможет!

Танос
источник
Это выполнимо, если у меня мало столбцов, я должен сказать, что у меня более 100 столбцов.
Станко
Я проверил ваше последнее редактирование, condition = (df.a == -1.001287)ожидая, что значения будут разделены на строку, в которой, a == -1.001287но я получил пустой фрейм данных.
Станко
Да, это потому , что это только дисплей, а не реальное значение, получить реальное значение , как это: df.iloc[1,0]. Или еще лучше установите значение самостоятельно, а затем попробуйте еще раз:df.iloc[1,0] = 1.2345; condition = df.a == 1.2345
Танос
Я не слежу, почему именно condition = (df.a == -1.001287)не работает?
Станко
8
ixтеперь устарела.
dbliss 04