パンダで特定の条件が満たされた行の値を更新します


98

次のデータフレームがあるとします。

テーブル

ストリーム2番の場合、列featおよびanother_featの値を更新する最も効率的な方法は何ですか?

これでしょうか?

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

更新: 100を超える列がある場合はどうすればよいですか?更新する列に明示的に名前を付けたくありません。各列の値を2で割りたい(ストリーム列を除く)。

だから私の目標が何であるかを明確にするために:

すべての値をストリーム2を持つすべての行の2で除算しますが、ストリーム列は変更しません

回答:


204

loc2つの列を同じ値に更新する必要がある場合に使用できると思います。

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

個別に更新する必要がある場合は、次の1つのオプションを使用します。

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

質問を更新しました。100を超える列がありますが、どうすればよいですか?
スタンコ2016

1
@ Stanko-別の質問だと思います-この100列を何らかの方法で選択する必要があります。たとえば、100最初の列が必要な場合は、を使用df.columns[:100]してからに渡しlocます。
jezrael 2016

最初の100列は必ずしも必要ではありません。列のすべての値(ストリーム列を除く)を2で除算したいだけです。ここで、ストリームはfe 2です
Stanko

したがって、locとnp.whereの違いは、locは条件を満たすだけの行を変更しますが、np.whereにはifおよびelseステートメントがあるため、すべての行が変更されるということです。
アンブル

1
@ Ambleu-まさに。
jezrael

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を超える列があると言っておく必要があります。
スタンコ2016

condition = (df.a == -1.001287)値が行の分割されることを期待して最後の編集をテストしましたa == -1.001287が、空のデータフレームが返されました。
スタンコ2016

はい、これは実際の値ではなく単なる表示であるため、次のように実際の値を取得しますdf.iloc[1,0]。いっそ自分で値を設定し、再度試してください:df.iloc[1,0] = 1.2345; condition = df.a == 1.2345
サノス

私はフォローしていませcondition = (df.a == -1.001287)ん、なぜ正確に機能しないのですか?
スタンコ2016

8
ix現在は非推奨です。
dbliss 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.