인덱스를 사용하여 팬더 DataFrame의 특정 셀에 대한 값 설정


478

팬더 데이터 프레임을 만들었습니다

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

그리고 이것을 얻었다

    xy
NaN NaN
B NaN NaN
C NaN NaN


그런 다음 행 'C'와 열 'x'와 같은 특정 셀에 값을 할당하고 싶습니다. 나는 그런 결과를 얻을 것으로 기대했다.

    xy
NaN NaN
B NaN NaN
C 10 NaN

이 코드로 :

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

그러나 내용은 df바뀌지 않았습니다. 그것은 다시 NaNDataFrame 에만 있습니다.

어떤 제안?


29
'체인 인덱싱'( df['x']['C'])을 사용 하지 마십시오 df.ix['x','C'].
Yariv

3
인덱스 액세스 순서는 다음 dataframe[column (series)] [row (Series index)]과 같아야하지만 많은 사람 (자신 포함)이이 dataframe[row][column]순서에 더 익숙합니다 . Matlab과 R 프로그래머로서 후자는 나에게 더 직관적 인 느낌이지만 분명히 Pandas가 작동하는 방식은 아닙니다.
Zhubarb

1
나는 그것을 시도했지만 다른 행 이름 x와 다른 열 이름 C를 추가했다. 행을 먼저 한 다음 열을 수행해야합니다. df.ix [ 'C', 'x'] = 10
마태 복음

5
@Yariv의 의견. 경고 : 0.20.0부터는 더 엄격한 .iloc 및 .loc 인덱서를 위해 .ix ​​인덱서가 더 이상 사용되지 않습니다. pandas.pydata.org/pandas-docs/stable/generated/… . df.at는 붙어있는 것처럼 보입니다.
jeffhale

답변:


592

RukTech의 대답은 , df.set_value('C', 'x', 10)멀리 멀리 더 빨리 내가 아래에 제시 한 옵션보다. 그러나 더 이상 사용되지 않을 예정입니다 .

앞으로 권장되는 방법은.iat/.at 입니다.


df.xs('C')['x']=10작동하지 않습니까?

df.xs('C')기본적으로 데이터 사본 이 포함 된 새 데이터 프레임 반환 하므로

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

이 새 데이터 프레임 만 수정합니다.

df['x']df데이터 프레임 의 뷰를 반환 하므로

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

df자신을 수정 합니다.

경고 : 작업이 복사본 또는 뷰를 반환하는지 예측하기 어려운 경우가 있습니다. 이러한 이유로 문서는 "chained indexing"으로 할당을 피하는 것이 좋습니다 .


따라서 권장되는 대안은

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

이는 않습니다 수정 df.


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

같은 것은 없다 df.xAPI는 . 무슨 소리 야?
smci

3
@smci : 'x'는의 열 이름입니다 df. column의 값과 함께 df.xa Series를 반환합니다 x. df['x']이 표기법은 (점 표기법과 달리) 모든 열 이름과 함께 작동 하기 때문에로 변경하고 더 명확하다고 생각합니다.
unutbu

1
나는 당신이 df.x함께 알려지지 않은 새로운 방법 이라고 말하는 줄 알았는데df.xs, df.ix
smci

df.xs(..., copy=True)사본을 반환하며 이것이 기본 동작입니다. df.xs(..., copy=False)원본을 반환합니다.
smci

7
관리자에 따르면 권장되는 값 설정 방법은 아닙니다. stackoverflow.com/a/21287235/1579844 및 내 답변을 참조하십시오 .
Yariv

224

업데이트 : .set_value메소드가 더 이상 사용되지 않습니다 . .iat/.at안타깝게도 팬더는 문서를 거의 제공하지 않습니다.


가장 빠른 방법은 set_value를 사용하는 것 입니다. 이 방법은 방법보다 ~ 100 배 빠릅니다 .ix. 예를 들면 다음과 같습니다.

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


5
보다 낫다 df['x']['C'] = 10 .
ALH

6
1000 루프, 루프 당 3 : 195 µs 최고 "df [ 'x'] [ 'C'] = 10"1000 루프, 루프 당 3 : 310 µs 최고 : "df.ix [ 'C', 'x'] = 10 "1000 루프, 최고 3 : 189 µs 루프 당"df.xs ( 'C', copy = False) [ 'x'] = 10 "1000 루프, 최고 3 : 3.22 µs 루프 당"df.set_value ( 'C', 'x', 10) "
propjk007

1
데이터 프레임에 새 행 / 콜을 추가 할 때도 작동합니까?
st.ph.n

그렇습니다 (팬더 0.16.2의 경우)
RukTech

이것을 사용하여 값을 df=df.append(df.sum(numeric_only=True),ignore_index=True)? 로 설정할 수 있습니까?
ctrl-alt-delete

94

다음 .loc과 같이 조건부 조회를 사용할 수도 있습니다 .

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

여기서 변수 <some_column_name를 확인하려는 열이 있고 추가하려는 열이 있습니다 (새 열 또는 이미 존재하는 열일 수 있음). 해당 열 / 행에 추가하려는 값입니다.<condition><another_column_name><value_to_add>

이 예제는 당면한 질문에 정확하게 작동하지 않지만 조건에 따라 특정 값을 추가하려는 경우 유용 할 수 있습니다.


8
두 번째 열은 대괄호로 묶어야하며, 그렇지 않으면 모든 열을 값으로 덮어 씁니다. : 이것처럼df.loc[df['age']==3, ['age-group']] = 'toddler'
Piizei

<some_column_name>이 내 인덱스 (unixtime index say)이고 아직 종료되지 않은 타임 스탬프 (예 : 새 타임 스탬프 읽기)를 추가하려고 할 때이 기능을 사용할 수 없습니다. 이견있는 사람?
yeliabsalohcin 2018 년

인덱스 및 셀 값을 기반으로 값을 변경할 수 있습니까?
BND

@ BND 확실하지 않지만이 명백한 함정을 피할 수는 있지만 색인 열을 동일한 값을 가진 다른 열과 복제하면됩니까? 짧은 대답은 모르겠다.
Blairg23

@yeliabsalohcin 위의 답변을 참조하십시오.
Blairg23

40

값을 설정하는 권장되는 방법은 (관리자에 따라) 다음과 같습니다.

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

'체인 인덱싱'( df['x']['C'])을 사용하면 문제가 발생할 수 있습니다.

보다:


7
ix더 이상 사용되지 않습니다 : pandas-docs.github.io/pandas-docs-travis/…
ecoe

완벽하게 작동합니다! 언젠가는 더 이상 사용되지 않을 것입니다!
Pavlos Ponos

35

사용해보십시오 df.loc[row_index,col_indexer] = value


6
스택 오버플로에 오신 것을 환영합니다! 코드의 기능과 문제를 해결하는 이유에 대한 설명을 추가하려면 게시물을 수정하십시오. 작동하는 경우에도 대부분 코드 만 포함 된 답변은 OP가 문제를 이해하는 데 도움이되지 않습니다. 또한 추측 일 경우 답변을 게시하지 않는 것이 좋습니다. 좋은 답변은 OP의 문제를 해결할 수있는 이유에 대한 그럴듯한 이유가 있습니다.
SuperBiasedMan

22

이것은 나를 위해 일한 유일한 것입니다!

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

.loc 여기에 대해 자세히 알아보십시오 .


않았다 .loc교체 .iat/.at?
가브리엘 페어

1
at와 비슷 loc하지만 둘 다 레이블 기반 조회를 제공합니다. atDataFrame 또는 Series에서 단일 값만 가져 오거나 설정해야하는 경우에 사용하십시오 . 에서 padas의 문서
Rutrus

인덱스 요소가 숫자 일 때 이것이 나에게 도움이되었습니다.
Christopher John

숫자와 문자열 인덱스의 혼합에서는 작동하지 않습니다.
Seanny123

12

.iat/.at좋은 해결책입니다. 이 간단한 data_frame이 있다고 가정합니다.

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

우리가 셀의 값을 수정하려면 [0,"A"]u는 그 해결책 중 하나를 사용할 수 있습니다 :

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

다음은 iat셀 값을 가져오고 설정 하는 데 사용하는 전체 예제 입니다.

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

y_train 전 :

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

iat각 셀의 값에 2를 곱하도록 변경 하는 사전 추정 기능을 호출 한 후 y_train :

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

8

값을 설정하려면 다음을 사용하십시오.

df.at[0, 'clm1'] = 0
  • 변수 설정에 가장 권장되는 방법입니다.
  • set_value, ix사용 중지되었습니다.
  • 경고없이 달리 iloc하고loc


6

사용할 수 있습니다 .iloc.

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

이 방법은 몇 가지 값을 지원하지 않는 것 같습니다 (예 : df.iloc[[2:8], [0]] = [2,3,4,5,6,7]방법 df.loc()이 기본적으로 수행).
strpeter

1
사용 중단 경고없이 완벽하게 작동합니다!
Pavlos Ponos

6

내 예에서는 선택한 셀에서 변경했습니다.

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

'result'는 'weight'열이있는 dataField입니다.


4

set_value() 더 이상 사용되지 않습니다.

릴리스 0.23.4부터 Pandas는 " 미래를 발표합니다 ..."

>>> 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

이 조언을 고려할 때 다음은 조언을 사용하는 방법에 대한 데모입니다.

  • 행 / 열 정수 위치

>>> 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
  • 행 / 열 레이블 별

>>> 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

참고 문헌 :


3

다음은 정수 및 문자열로 인덱싱 된 데이터 프레임에 대해 모든 사용자가 제공 한 유효한 솔루션에 대한 요약입니다.

df.iloc, df.loc 및 df.at는 두 유형의 데이터 프레임 모두에서 작동하며 df.iloc은 행 / 열 정수 인덱스, df.loc 및 df.at는 열 이름 및 / 또는 정수 인덱스를 사용한 값 설정을 지원합니다. .

지정된 인덱스가 존재하지 않으면 df.loc과 df.at는 새로 삽입 된 행 / 열을 기존 데이터 프레임에 추가하지만 df.iloc은 "IndexError : 위치 인덱서가 범위를 벗어났습니다"를 발생시킵니다. Python 2.7 및 3.7에서 테스트 한 실제 예제는 다음과 같습니다.

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

테스트를 거쳤으며 출력이 df.set_value조금 더 빠르지 만 공식 방법 df.at은 더 이상 사용되지 않는 가장 빠른 방법 처럼 보입니다.

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)

이것은 단일 셀의 값을 설정하는 것입니다. 벡터의 경우 lociloc그들이 벡터화되어 있기 때문에 더 나은 옵션이 있어야합니다.


3

조건과 함께 인덱스를 사용하는 한 가지 방법은 먼저 조건을 만족하는 모든 행의 인덱스를 얻은 다음 여러 방법으로 해당 행 인덱스를 사용하는 것입니다

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

예시 조건은

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

그런 다음이 행 색인을 다양한 방법으로 사용할 수 있습니다

  1. conditional_index에 대한 하나의 열 값을 바꿉니다.
df.loc[conditional_index , [col name]]= <new value>
  1. conditional_index의 여러 열 값 바꾸기
df.loc[conditional_index, [col1,col2]]= <new value>
  1. conditional_index를 저장하면 한 행의 값을 동일한 행 인덱스로 다른 열에 할당 할 수 있다는 이점이 있습니다
df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col name']

.index는 .loc이 직접 주소 지정과 함께 사용할 수있는 인덱스 배열을 반환하므로 순회를 반복하지 않기 때문에 가능합니다.


행 변경은 어떻습니까?
FabioSpaghetti

그냥 df.loc [conditional_index,] = <새 값>을 사용하십시오. 조건을 만족하는 모든 행 열의 새 값을 대체합니다
Atta Jutt

2

df.loc['c','x']=10c 번째 행과 x 번째 열의 값이 변경 됩니다.


1

위의 답변 외에도 기존 데이터 프레임에 데이터 행을 추가하는 다양한 방법을 비교하는 벤치 마크가 있습니다. at 또는 set-value를 사용하는 것이 큰 데이터 프레임에 대해 가장 효율적인 방법임을 보여줍니다 (적어도 이러한 테스트 조건에서는).

  • 각 행에 대한 새 데이터 프레임을 만들고 ...
    • ... 첨부 (13.0 초)
    • ... 연결 (13.1 초)
  • 모든 새로운 행을 다른 컨테이너에 먼저 저장하고 새 데이터 프레임으로 한 번 변환하고 추가하십시오 ...
    • 컨테이너 = 목록 목록 (2.0 초)
    • 컨테이너 = 목록 사전 (1.9 초)
  • 전체 데이터 프레임을 미리 할당하고 새 행과 모든 열을 반복하고 다음을 사용하여 채 웁니다.
    • ... (0.6 초)
    • ..._ 값 (0.4 초)

테스트를 위해 100,000 개의 행과 1,000 개의 열과 임의의 숫자 값으로 구성된 기존 데이터 프레임이 사용되었습니다. 이 데이터 프레임에 100 개의 새로운 행이 추가되었습니다.

코드는 아래를 참조하십시오.

#!/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

전체 행이 아닌 일부 열에 대해서만 값을 변경하려는 경우 :

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

0

버전 0.21.1부터 .at메소드 를 사용할 수도 있습니다 . 여기에 .loc언급 된 것처럼 pandas .at 대 .loc 과는 약간의 차이가 있지만 단일 값 교체가 더 빠릅니다.


0

So, [ 'x', C]의 NaN을 값 10으로 변환하는 질문

정답은..

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

대체 코드는

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

-4

나도이 주제를 찾고 있었고 DataFrame을 반복하고 두 번째 DataFrame의 조회 값으로 업데이트하는 방법을 모았습니다. 여기 내 코드가 있습니다.

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'])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.