Perbarui nilai baris di mana kondisi tertentu terpenuhi di panda

96

Katakanlah saya memiliki dataframe berikut:

meja

Apa cara yang paling efisien untuk memperbarui nilai kolom feat dan another_feat di mana alirannya nomor 2 ?

Apakah ini?

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

UPDATE: Apa yang harus saya lakukan jika saya memiliki lebih dari 100 kolom? Saya tidak ingin secara eksplisit memberi nama kolom yang ingin saya perbarui. Saya ingin membagi nilai setiap kolom dengan 2 (kecuali untuk kolom aliran).

Jadi untuk memperjelas apa tujuan saya:

Membagi semua nilai dengan 2 dari semua baris yang memiliki aliran 2, tetapi tidak mengubah kolom aliran

Stanko
sumber

Jawaban:

199

Saya pikir Anda dapat menggunakan locjika Anda perlu memperbarui dua kolom ke nilai yang sama:

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

Jika Anda memerlukan pembaruan terpisah, salah satu opsi digunakan:

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

Opsi umum lainnya adalah penggunaan 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

EDIT: Jika Anda perlu membagi semua kolom tanpa streamkondisinya True, gunakan:

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
sumber
Saya memperbarui pertanyaan saya, saya memiliki lebih dari 100 kolom, bagaimana saya bisa melakukan ini?
Stanko
1
@Stanko - Saya pikir ini adalah pertanyaan lain - Anda perlu memilih 100kolom ini dengan cara tertentu. misalnya jika membutuhkan 100kolom pertama, gunakan df.columns[:100]dan kemudian diteruskan ke loc.
jezrael
Saya tidak perlu 100 kolom pertama, saya hanya ingin membagi semua nilai kolom (kecuali kolom aliran) dengan 2 di mana alirannya adalah fe 2
Stanko
jadi perbedaan antara loc dan np.where adalah bahwa loc mengubah baris yang hanya memenuhi kondisi tetapi np.where memiliki pernyataan if dan else sehingga itu akan mengubah semua baris?
Ambleu
1
@Ambleu - tepatnya.
jezrael
3

Anda dapat melakukan hal yang sama dengan .ix, seperti ini:

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

EDIT

Setelah informasi tambahan, berikut ini akan mengembalikan semua kolom - di mana beberapa kondisi terpenuhi - dengan nilai yang dibelah dua:

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

Saya harap ini membantu!

Thanos
sumber
Ini bisa dilakukan jika saya tidak memiliki banyak kolom, saya harus mengatakan bahwa saya memiliki lebih dari 100 kolom.
Stanko
Saya menguji hasil edit terakhir Anda dengan condition = (df.a == -1.001287)mengharapkan nilai-nilai dibagi dari baris di mana a == -1.001287tetapi saya mendapatkan kembali kerangka data kosong.
Stanko
Ya, ini karena ini hanya tampilan, bukan nilai riil, mendapatkan nilai riil seperti ini: df.iloc[1,0]. Atau lebih baik lagi tetapkan nilainya sendiri dan kemudian coba lagi:df.iloc[1,0] = 1.2345; condition = df.a == 1.2345
Thanos
Saya tidak mengikuti, mengapa sebenarnya condition = (df.a == -1.001287)tidak berhasil?
Stanko
8
ixsekarang tidak digunakan lagi.
Bliss