İndeks kullanarak panda DataFrame'deki belirli bir hücrenin değerini ayarlama


478

Bir Panda DataFrame oluşturdum

df = DataFrame(index=['A','B','C'], columns=['x','y'])

ve bunu aldım

    xy
A NaN NaN
B NaN NaN
C NaN NaN


Sonra belirli bir hücreye, örneğin 'C' satırı ve 'x' sütunu için değer atamak istiyorum. Böyle bir sonuç almayı bekledim:

    xy
A NaN NaN
B NaN NaN
C 10 NaN

bu kodla:

df.xs('C')['x'] = 10

ama içeriği dfdeğişmedi. Yine sadece NaNDataFrame içinde.

Herhangi bir öneri?


29
'Zincirleme indeksleme' ( df['x']['C']) kullanmayın, kullanın df.ix['x','C'].
Yariv

3
Dizin erişim sırasının olması gerekir: dataframe[column (series)] [row (Series index)]oysa birçok kişi (ben dahil) dataframe[row][column]siparişe daha çok alışır. Bir Matlab ve R programcısı olarak, ikincisi bana daha sezgisel geliyor ama görünüşe göre
Pandas'ın

1
i denedim, ama başka bir satır adları x ve başka bir sütun adları C ekleyerek sona erdi. df.ix ['C', 'x'] = 10
Matthew

5
@ Yariv adlı kullanıcının yorumu. Uyarı: 0.20.0'dan başlayarak, .ix dizinleyicisi daha katı .iloc ve .loc dizinleyicileri lehine kullanımdan kaldırılmıştır. pandas.pydata.org/pandas-docs/stable/generated/… . df.at etrafta dolanıyor gibi görünüyor.
jeffhale

Yanıtlar:


592

RukTech'in cevabı ,, df.set_value('C', 'x', 10)aşağıda önerdiğim seçeneklerden çok daha hızlı. Ancak, kullanımdan kaldırılması planlanmaktadır .

İleride, önerilen yöntem.iat/.at .


Neden df.xs('C')['x']=10çalışmıyor:

df.xs('C')varsayılan olarak, verilerin bir kopyasını içeren yeni bir veri çerçevesi döndürür.

df.xs('C')['x']=10

yalnızca bu yeni veri çerçevesini değiştirir.

df['x']bir görünümü verir df, böylece dataframe

df['x']['C'] = 10

dfkendini değiştirir .

Uyarı : Bir işlemin bir kopya veya görünüm döndürüp döndürmediğini tahmin etmek bazen zor olabilir. Bu nedenle dokümanlar "zincirleme endeksleme" içeren atamalardan kaçınmayı önerir .


Bu yüzden önerilen alternatif

df.at['C', 'x'] = 10

hangi değişiklik yapardf .


In [18]: %timeit df.set_value('C', 'x', 10)
100000 loops, best of 3: 2.9 µs per loop

In [20]: %timeit df['x']['C'] = 10
100000 loops, best of 3: 6.31 µs per loop

In [81]: %timeit df.at['C', 'x'] = 10
100000 loops, best of 3: 9.2 µs per loop

Diye bir şey yoktur df.xyılında API . Ne demek istedin?
smci

3
@smci: 'x'içindeki bir sütunun adıdır df. sütundaki değerleri içeren df.xbir a döndürür . Ben bunu değiştireceğiz bu notasyonu (nokta gösterimde aksine) herhangi bir sütun adı ile çalışacak beri ben daha net olduğunu düşünüyorum. Seriesxdf['x']
unutbu

1
Biliyordum, senin df.xyanında bilinmeyen yeni bir yöntem olduğunu söylediğini sanıyordumdf.xs, df.ix
smci

df.xs(..., copy=True)bir kopya döndürür ve bu varsayılan davranıştır. df.xs(..., copy=False)orijinali döndürür.
smci

7
Koruyuculara göre, bu bir değer belirlemenin önerilen yolu değildir. Bkz. Stackoverflow.com/a/21287235/1579844 ve cevabım.
Yariv

224

Güncelleme: .set_valueYöntem kullanımdan kaldırılacak . .iat/.atiyi yedekler, ne yazık ki pandalar az dokümantasyon sağlar


Bunu yapmanın en hızlı yolu set_value kullanmaktır . Bu yöntem, yöntemden ~ 100 kat daha hızlıdır .ix. Örneğin:

df.set_value('C', 'x', 10)


5
Bundan daha iyi df['x']['C'] = 10 .
ALH

6
1000 döngü, en iyi 3: 195 µs döngü başına "df ['x'] ['C'] = 10" 1000 döngü, en iyi 3: 310 µs döngü başına "df.ix ['C', 'x'] = 10 "1000 döngü, döngü başına en iyi 3: 189 µs " df.xs ('C', kopya = Yanlış) ['x'] = 10 "1000 döngü, döngü başına en iyi 3: 7,22 µs " df.set_value ('C', 'x', 10) "
propjk007

1
bu da veri çerçevesine yeni bir satır / sütun eklemek için çalışıyor mu?
16:46

Evet öyle (pandalar için 0.16.2)
RukTech

Bunu bir değeri bir değere ayarlamak için kullanmak mümkün müdür df=df.append(df.sum(numeric_only=True),ignore_index=True)?
ctrl-alt-delete

94

Ayrıca .locburada görüldüğü gibi bir koşullu aramayı da kullanabilirsiniz :

df.loc[df[<some_column_name>] == <condition>, [<another_column_name>]] = <value_to_add>

nerede <some_column_namedenetlemek istediğiniz sütun <condition>karşı değişken ve <another_column_name>sen eklemek istediğiniz sütun (yeni bir sütun veya zaten var biri olabilir). <value_to_add>bu sütuna / satıra eklemek istediğiniz değerdir.

Bu örnek eldeki soru ile tam olarak çalışmaz, ancak birisinin bir koşula bağlı olarak belirli bir değer eklemek istediği için yararlı olabilir.


8
ikinci sütunun parantez içinde olması gerekir, aksi takdirde tüm sütunların üzerine değer yazılır. df.loc[df['age']==3, ['age-group']] = 'toddler'
Şunun

<some_column_name> benim dizin (unixtime dizini söylemek) ve ben henüz çıkmaz (yani yeni bir zaman damgası okuma) bir zaman damgası eklemek çalışıyorum için bu alınamıyor. Düşüncesi olan var mı?
yeliabsalohcin

Bir değeri dizin ve hücre değerlerine göre değiştirmek mümkün müdür?
BND

@BND emin değilim, ama bu belirgin tuzak aşmak ama sadece aynı değeri olan başka bir sütun ile dizin sütun çoğaltabilir? Kısa cevap bilmiyorum.
Blairg23

@yeliabsalohcin yukarıdaki cevaba bakınız.
Blairg23

40

Bir değer ayarlamanın önerilen yolu (koruyuculara göre):

df.ix['x','C']=10

'Zincirleme indeksleme' ( df['x']['C']) kullanmak sorunlara yol açabilir.

Görmek:


7
ixkullanımdan kaldırıldı: pandas-docs.github.io/pandas-docs-travis/…
ecoe

mükemmel çalışıyor! bir ara kullanımdan kaldırılacak olsa da!
Pavlos Ponos

35

Kullanmayı deneyin df.loc[row_index,col_indexer] = value


6
Stack Overflow'a hoş geldiniz! Kodunuzun ne yaptığı ve sorunun neden çözüleceği hakkında daha fazla açıklama eklemek için lütfen yayınınızı düzenleyin. Çoğunlukla sadece kod içeren bir yanıt (çalışıyor olsa bile) genellikle OP'nin sorunlarını anlamalarına yardımcı olmaz. Ayrıca sadece bir tahminde bulunmanız durumunda da yanıt göndermemeniz önerilir. İyi bir yanıtın OP'nin sorununu neden çözebileceğine dair makul bir nedeni olacaktır.
SuperBiasedMan

22

Benim için işe yarayan tek şey bu!

df.loc['C', 'x'] = 10

.loc Burada daha fazla bilgi edinin .


did .locyerine .iat/.at?
Gabriel Fuarı

1
atBenzer şekilde loc, her ikisi de etiket tabanlı aramalar sağlar. atBir DataFrame veya Seride yalnızca tek bir değer almanız veya ayarlamanız gerekiyorsa kullanın . Gönderen padas doc
Rutrus

Güzel bu benim dizin öğeleri sayısal olduğunda benim için çalıştı.
Christopher John

Bu, sayısal ve dize dizinlerinin bir karışımı için işe yaramaz.
Seanny123

12

.iat/.atiyi bir çözümdür. Diyelim ki bu basit data_frame'iniz var:

   A   B   C
0  1   8   4 
1  3   9   6
2  22 33  52

[0,"A"]u hücresinin değerini değiştirmek istiyorsak , bu çözümlerden birini kullanabilirsiniz:

  1. df.iat[0,0] = 2
  2. df.at[0,'A'] = 2

İşte iathücre değerini almak ve ayarlamak için nasıl kullanılacağına dair tam bir örnek :

def prepossessing(df):
  for index in range(0,len(df)): 
      df.iat[index,0] = df.iat[index,0] * 2
  return df

y_önüşün:

    0
0   54
1   15
2   15
3   8
4   31
5   63
6   11

iather hücrenin değerini 2 ile çarpmak için değiştirilecek ön tahmin fonksiyonunu çağırdıktan sonra y_train :

     0
0   108
1   30
2   30
3   16
4   62
5   126
6   22

8

Değerleri ayarlamak için şunu kullanın:

df.at[0, 'clm1'] = 0
  • Değişkenleri ayarlamak için önerilen en hızlı yöntem.
  • set_value, ixkullanımdan kaldırıldı.
  • Hiçbir uyarı, aksine ilocveloc


6

kullanabilirsiniz .iloc.

df.iloc[[2], [0]] = 10

Bu yöntem, örneğin df.iloc[[2:8], [0]] = [2,3,4,5,6,7]yöntemin df.loc()doğal olarak yaptığı birkaç değeri desteklemiyor gibi görünmektedir .
strpeter

1
Kullanımdan kaldırma uyarısı olmadan mükemmel çalışır!
Pavlos Ponos

6

Örneğimde sadece seçilen hücrede değiştiriyorum

    for index, row in result.iterrows():
        if np.isnan(row['weight']):
            result.at[index, 'weight'] = 0.0

'sonuç', 'ağırlık' sütununa sahip bir dataField öğesidir


4

set_value() kullanımdan kaldırıldı.

0.23.4 sürümünden başlayarak, Pandalar " geleceği duyuruyor " ...

>>> df
                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        245.0
2      Chevrolet Malibu        190.0
>>> df.set_value(2, 'Prices (U$)', 240.0)
__main__:1: FutureWarning: set_value is deprecated and will be removed in a future release.
Please use .at[] or .iat[] accessors instead

                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        245.0
2      Chevrolet Malibu        240.0

Bu tavsiyeyi göz önünde bulundurarak, bunları nasıl kullanacağınıza dair bir gösteri:

  • satır / sütun tamsayı konumlarına göre

>>> df.iat[1, 1] = 260.0
>>> df
                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        260.0
2      Chevrolet Malibu        240.0
  • satır / sütun etiketlerine göre

>>> df.at[2, "Cars"] = "Chevrolet Corvette"
>>> df
                  Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        260.0
2    Chevrolet Corvette        240.0

Referanslar:


3

Burada, tamsayı ve dizgiyle dizinlenmiş veri çerçeveleri için tüm kullanıcılar tarafından sağlanan geçerli çözümlerin bir özeti bulunmaktadır.

df.iloc, df.loc ve df.at her iki veri çerçevesi türü için çalışır, df.iloc yalnızca satır / sütun tamsayı dizinleriyle çalışır, df.loc ve df.at, sütun adları ve / veya tamsayı dizinleri kullanarak değerleri ayarlamak için destekler .

Belirtilen dizin mevcut olmadığında, hem df.loc hem de df.at, yeni eklenen satırları / sütunları varolan veri çerçevesine ekler, ancak df.iloc "IndexError: konum dizinleyicileri sınırların dışında" değerini yükseltir. Python 2.7 ve 3.7'de test edilen bir çalışma örneği aşağıdaki gibidir:

import numpy as np, pandas as pd

df1 = pd.DataFrame(index=np.arange(3), columns=['x','y','z'])
df1['x'] = ['A','B','C']
df1.at[2,'y'] = 400

# rows/columns specified does not exist, appends new rows/columns to existing data frame
df1.at['D','w'] = 9000
df1.loc['E','q'] = 499

# using df[<some_column_name>] == <condition> to retrieve target rows
df1.at[df1['x']=='B', 'y'] = 10000
df1.loc[df1['x']=='B', ['z','w']] = 10000

# using a list of index to setup values
df1.iloc[[1,2,4], 2] = 9999
df1.loc[[0,'D','E'],'w'] = 7500
df1.at[[0,2,"D"],'x'] = 10
df1.at[:, ['y', 'w']] = 8000

df1
>>> df1
     x     y     z     w      q
0   10  8000   NaN  8000    NaN
1    B  8000  9999  8000    NaN
2   10  8000  9999  8000    NaN
D   10  8000   NaN  8000    NaN
E  NaN  8000  9999  8000  499.0

3

Test ettim ve çıktı df.set_valuebiraz daha hızlı, ancak resmi yöntem df.atbunu yapmanın en hızlı kullanılmayan yoluna benziyor.

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(100, 100))

%timeit df.iat[50,50]=50 # ✓
%timeit df.at[50,50]=50 #  ✔
%timeit df.set_value(50,50,50) # will deprecate
%timeit df.iloc[50,50]=50
%timeit df.loc[50,50]=50

7.06 µs ± 118 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
5.52 µs ± 64.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
3.68 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
98.7 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
109 µs ± 1.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Bunun tek bir hücrenin değerini ayarladığını unutmayın. Vektörler için locve iloconlar vectorized beri iyi seçenekler olmalıdır.


3

Dizinini koşulla kullanmanın bir yolu, önce durumunuzu karşılayan tüm satırların dizinini almak ve daha sonra bu satır dizinlerini birden çok şekilde kullanmaktır.

conditional_index = df.loc[ df['col name'] <condition> ].index

Örnek durum şöyle

==5, >10 , =="Any string", >= DateTime

Ardından bu satır dizinlerini çeşitli şekillerde kullanabilirsiniz.

  1. Conditional_index için bir sütunun değerini değiştirin
df.loc[conditional_index , [col name]]= <new value>
  1. Conditional_index için birden çok sütunun değerini değiştirin
df.loc[conditional_index, [col1,col2]]= <new value>
  1. Conditional_index işlevini kaydetmenin bir yararı, bir sütunun değerini aynı satır dizinine sahip başka bir sütuna atayabilmenizdir
df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col name']

Tüm bunlar mümkündür.


satır değiştirmeye ne dersiniz?
FabioSpaghetti

sadece kullanın, df.loc [conditional_index,] = <new value>
Koşulu

2

df.loc['c','x']=10 Bu, c. Satır ve x. Sütununun değerini değiştirir .


1

Yukarıdaki yanıtlara ek olarak, zaten mevcut bir veri çerçevesine veri satırları eklemenin farklı yollarını karşılaştıran bir karşılaştırma ölçütü. Büyük veri çerçeveleri için (en azından bu test koşulları için) at veya set-value kullanmanın en etkili yol olduğunu gösterir.

  • Her satır için yeni veri çerçevesi oluşturun ve ...
    • ... ekle (13.0 s)
    • ... bitiştir (13.1 s)
  • Önce tüm yeni satırları başka bir kapta saklayın, bir kez yeni veri çerçevesine dönüştürün ve ekleyin ...
    • container = liste listeleri (2,0 sn)
    • container = listeler sözlüğü (1.9 s)
  • Tüm veri çerçevesini yeniden konumlandırın, yeni satırlar ve tüm sütunlar üzerinde yineleyin ve kullanarak doldurun
    • ... (0,6 sn.)
    • ... set_value (0,4 sn)

Test için 100.000 satır ve 1.000 sütun ve rastgele numpy değerleri içeren mevcut bir veri çerçevesi kullanıldı. Bu veri çerçevesine 100 yeni satır eklendi.

Kod aşağıya bakın:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 21 16:38:46 2018

@author: gebbissimo
"""

import pandas as pd
import numpy as np
import time

NUM_ROWS = 100000
NUM_COLS = 1000
data = np.random.rand(NUM_ROWS,NUM_COLS)
df = pd.DataFrame(data)

NUM_ROWS_NEW = 100
data_tot = np.random.rand(NUM_ROWS + NUM_ROWS_NEW,NUM_COLS)
df_tot = pd.DataFrame(data_tot)

DATA_NEW = np.random.rand(1,NUM_COLS)


#%% FUNCTIONS

# create and append
def create_and_append(df):
    for i in range(NUM_ROWS_NEW):
        df_new = pd.DataFrame(DATA_NEW)
        df = df.append(df_new)
    return df

# create and concatenate
def create_and_concat(df):
    for i in range(NUM_ROWS_NEW):
        df_new = pd.DataFrame(DATA_NEW)
        df = pd.concat((df, df_new))
    return df


# store as dict and 
def store_as_list(df):
    lst = [[] for i in range(NUM_ROWS_NEW)]
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            lst[i].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(lst)
    df_tot = df.append(df_new)
    return df_tot

# store as dict and 
def store_as_dict(df):
    dct = {}
    for j in range(NUM_COLS):
        dct[j] = []
        for i in range(NUM_ROWS_NEW):
            dct[j].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(dct)
    df_tot = df.append(df_new)
    return df_tot




# preallocate and fill using .at
def fill_using_at(df):
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            #print("i,j={},{}".format(i,j))
            df.at[NUM_ROWS+i,j] = DATA_NEW[0,j]
    return df


# preallocate and fill using .at
def fill_using_set(df):
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            #print("i,j={},{}".format(i,j))
            df.set_value(NUM_ROWS+i,j,DATA_NEW[0,j])
    return df


#%% TESTS
t0 = time.time()    
create_and_append(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
create_and_concat(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
store_as_list(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
store_as_dict(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
fill_using_at(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
fill_using_set(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

0

Tüm satırın değil, yalnızca bazı sütunların değerlerini değiştirmek istiyorsanız:

x = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
x.iloc[1] = dict(A=10, B=-10)


0

Soo, NaN'yi ['x', C] 'de 10 değerine dönüştürmek için sorunuz

cevap..

df['x'].loc['C':]=10
df

alternatif kod

df.loc['C':'x']=10
df

-4

Ben de bu konuyu arıyordum ve bir DataFrame üzerinden yineleme ve ikinci bir DataFrame arama değerleri ile güncellemek için bir yol koymak. İşte kodum.

src_df = pd.read_sql_query(src_sql,src_connection)
for index1, row1 in src_df.iterrows():
    for index, row in vertical_df.iterrows():
        src_df.set_value(index=index1,col=u'etl_load_key',value=etl_load_key)
        if (row1[u'src_id'] == row['SRC_ID']) is True:
            src_df.set_value(index=index1,col=u'vertical',value=row['VERTICAL'])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.