इंडेक्स का उपयोग करते हुए पांडास डेटाफ्रैम में विशेष सेल के लिए मूल्य निर्धारित करें


477

मैंने पंडों का डेटाफ़्रेम बनाया है

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

और यह मिल गया

    xy
एक NaN NaN
ब नाइ NaN
C एनएएन NaN


फिर मैं विशेष सेल के लिए मान निर्दिष्ट करना चाहता हूं, उदाहरण के लिए पंक्ति 'C' और कॉलम 'x'। मुझे ऐसा परिणाम मिलने की उम्मीद है:

    xy
एक NaN NaN
ब नाइ NaN
C 10 NaN

इस कोड के साथ:

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

लेकिन सामग्री dfनहीं बदली है। यह फिर से केवल NaNDataFrame में है।

कोई सुझाव?


29
'जंजीर अनुक्रमण' ( df['x']['C']) का उपयोग न करें df.ix['x','C']
यरीव

3
सूचकांक पहुंच के क्रम की आवश्यकता है: dataframe[column (series)] [row (Series index)]जबकि कई लोग (स्वयं सहित) dataframe[row][column]आदेश के लिए अधिक उपयोग किए जाते हैं । मतलब और आर प्रोग्रामर के रूप में उत्तरार्द्ध मेरे लिए अधिक सहज महसूस करता है, लेकिन यह स्पष्ट रूप से पंडों के काम करने का तरीका नहीं है ..
झब्बारब

1
मैंने कोशिश की है कि, लेकिन मैं एक और पंक्ति नाम x और एक और स्तंभ नाम जोड़ने के लिए समाप्त हो गया। आपको पंक्ति को पहले स्तंभ फिर करना होगा। so df.ix ['C', 'x'] = 10
मैथ्यू

5
@ यारिव की टिप्पणी के लिए। चेतावनी: 0.20.0 में शुरू, .ix इंडेक्स को अधिक सख्त .iloc और .loc इंडेक्सर्स के पक्ष में पदावनत किया जाता है। pandas.pydata.org/pandas-docs/stable/generated/… । df.at ऐसा लगता है जैसे यह चारों ओर चिपका हुआ है।
जेफेल

जवाबों:


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खुद को संशोधित करता है।

चेतावनी : कभी-कभी यह अनुमान लगाना मुश्किल होता है कि कोई ऑपरेशन कॉपी या दृश्य देता है या नहीं। इस कारण डॉक्स "जंजीर अनुक्रमण" वाले असाइनमेंट से बचने की सलाह देते हैं


तो अनुशंसित विकल्प है

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.x में ऐसी कोई बात नहीं है । आप क्या मतलब था?
एसएमसीआई

3
@smci: 'x'एक कॉलम का नाम है df। कॉलम में मानों के साथ df.xलौटता है । मैं इसे बदल दूंगा क्योंकि यह नोटेशन किसी भी कॉलम नाम (डॉट नोटेशन के विपरीत) के साथ काम करेगा और मुझे लगता है कि यह स्पष्ट है। Seriesxdf['x']
अनटु

1
मुझे पता था कि, मुझे लगा कि आप कह रहे हैं कि df.xकुछ अज्ञात नई विधि हैdf.xs, df.ix
smci

df.xs(..., copy=True)एक प्रति लौटाता है, और वह है डिफ़ॉल्ट व्यवहार। df.xs(..., copy=False)मूल लौटाता है।
एसएमसीआई

7
अनुरक्षकों के अनुसार, यह मूल्य निर्धारित करने का अनुशंसित तरीका नहीं है। Stackoverflow.com/a/21287235/1579844 और मेरा उत्तर देखें ।
यरिव

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 ds प्रति लूप "df ['x'] ['C'] = 10" 1000 लूप, सर्वश्रेष्ठ 3: 310 µs प्रति लूप "df.ix ['C', 'x]] = 10 "1000 लूप, सर्वश्रेष्ठ 3: 189 µ प्रति लूप" df.xs ('C', कॉपी = गलत) ['x'] = 10 "1000 लूप, सर्वश्रेष्ठ 3: 7.22 µ प्रति लूप - df.set_value ('C', 'x', 10) "
propjk007

1
क्या यह डेटाफ़्रेम में एक नई पंक्ति / कॉल जोड़ने के लिए भी काम करता है?
st.ph.n

हाँ यह करता है (पांडा 0.16.2 के लिए)
रुटेक

क्या किसी मान पर सेट करने के लिए इसका उपयोग करना संभव है 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'
पाइजेई

मुझे यह काम करने के लिए नहीं मिल सकता है जब <some_column_name> मेरा सूचकांक है (यूनिक्सटाइम इंडेक्स कहता है) और मैं एक टाइमस्टैम्प जोड़ने की कोशिश कर रहा हूं जो अभी तक बाहर नहीं निकला है (यानी एक नया टाइमस्टैम्प रीडिंग)। कोई विचार?
yeliabsalohcin

क्या इंडेक्स और सेल वैल्यू के आधार पर मूल्य बदलना संभव है?
बीएनडी

@ बीएनडी मुझे यकीन नहीं है, लेकिन आप इस स्पष्ट नुकसान के आसपास हो सकते हैं, लेकिन एक ही मूल्य के साथ दूसरे कॉलम के साथ सूचकांक कॉलम को दोहरा रहे हैं? संक्षिप्त जवाब है मुझे नहीं पता।
ब्लेयरग 23

@yeliabsalohcin उपरोक्त उत्तर देखें।
ब्लेयरग 23

40

मान सेट करने के लिए अनुशंसित तरीका (अनुरक्षकों के अनुसार) है:

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

'जंजीर अनुक्रमण' ( df['x']['C']) का उपयोग करने से समस्याएं हो सकती हैं।

देख:



सही काम करता है! हालांकि यह कुछ समय के लिए पदावनत होने वाला है!
पावलोस पोनोस

35

प्रयोग करके देखें df.loc[row_index,col_indexer] = value


6
ढेर अतिप्रवाह में आपका स्वागत है! कृपया अपने कोड को संपादित करने पर विचार करें कि आपका कोड क्या करता है और यह समस्या का समाधान क्यों करेगा, इसके बारे में अधिक विवरण जोड़ने के लिए। एक जवाब जो ज्यादातर सिर्फ कोड होता है (भले ही यह काम कर रहा हो) आमतौर पर ओपी को उनकी समस्या को समझने में मदद नहीं करेगा। यह भी अनुशंसा की जाती है कि आप एक उत्तर पोस्ट न करें यदि यह सिर्फ एक अनुमान है। एक अच्छा जवाब के पास एक प्रशंसनीय कारण होगा कि यह ओपी के मुद्दे को क्यों हल कर सकता है।
सुपरबाइडमैन

22

यह केवल एक चीज है जो मेरे लिए काम करती है!

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

.loc यहाँ के बारे में अधिक जानें ।


था .locकी जगह .iat/.at?
गेब्रियल फेयर

1
atइसके समान loc, इसमें दोनों लेबल-आधारित लुकअप प्रदान करते हैं। उपयोग करें atयदि आपको केवल DataFrame या Series में एकल मान प्राप्त करने या सेट करने की आवश्यकता है। से पद डॉक
Rutrus

यह मेरे लिए अच्छा था जब मेरे सूचकांक तत्व संख्यात्मक थे।
क्रिस्टोफर जॉन

यह संख्यात्मक और स्ट्रिंग सूचकांकों के मिश्रण के लिए काम नहीं करता है।
सीनिइज़

12

.iat/.atअच्छा उपाय है। मान लीजिए कि आपके पास यह सरल डेटा_फ्रेम है:

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

अगर हम सेल के मूल्य को संशोधित करना चाहते हैं, तो [0,"A"]आप उनमें से किसी एक समाधान का उपयोग कर सकते हैं:

  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

y_train को प्रीपॉसिंग फ़ंक्शन के बाद कॉल करना जो iatप्रत्येक सेल के मान को 2 से गुणा करना है:

     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()मूल रूप से करती है।
स्ट्रैपटर

1
सही काम करता है, बिना किसी चेतावनी के!
पावलोस पोनोस


4

set_value() पदावनत किया गया है।

0.23.4 रिलीज से शुरू, पंडों ने " भविष्य की घोषणा की " ...

>>> 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: positional indexers out-of-bounds" बढ़ाएगा। पायथन 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)

ध्यान दें कि यह एकल कक्ष के लिए मान सेट कर रहा है। वैक्टर के लिए locऔर ilocबेहतर विकल्प होने चाहिए क्योंकि वे सदिश हैं।


3

इंडेक्स को शर्त के साथ उपयोग करने का एक तरीका है कि पहले उन सभी पंक्तियों का इंडेक्स प्राप्त करें जो आपकी स्थिति को संतुष्ट करते हैं और फिर उन पंक्ति इंडेक्सों को कई तरीकों से उपयोग करते हैं

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

उदाहरण दशा जैसी है

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

फिर आप इन रो इंडेक्स को विभिन्न तरीकों से उपयोग कर सकते हैं

  1. सशर्त_इंडेक्स के लिए एक कॉलम का मान बदलें
df.loc[conditional_index , [col name]]= <new value>
  1. सशर्त_index के लिए कई कॉलम का मान बदलें
df.loc[conditional_index, [col1,col2]]= <new value>
  1. सशर्त_index को सहेजने के साथ एक लाभ यह है कि आप एक पंक्ति के मान को दूसरे स्तंभ के लिए एक ही पंक्ति सूचकांक के साथ निर्दिष्ट कर सकते हैं
df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col name']

यह सब संभव है क्योंकि .index इंडेक्स की एक सरणी देता है। जो डायरेक्ट एड्रेसिंग के साथ उपयोग कर सकता है इसलिए यह बार-बार ट्रैवर्सल्स से बचा जाता है।


पंक्तियों को बदलने के बारे में क्या?
फाबियोस्पेगेटी

बस उपयोग करें, df.loc [conditional_index]] = <नया मूल्य> यह पंक्तियों के सभी स्तंभों में नए मूल्य को प्रतिस्थापित करेगा जो शर्त को पूरा करता है
अट्टा जट्ट


1

उपरोक्त उत्तरों के अलावा, यहां एक बेंचमार्क है जो पहले से मौजूद डेटाफ्रेम में डेटा की पंक्तियों को जोड़ने के लिए विभिन्न तरीकों की तुलना करता है। यह दर्शाता है कि बड़े डेटाफ़्रेम (कम से कम इन परीक्षण स्थितियों के लिए) पर सबसे प्रभावी तरीका सेट या सेट-वैल्यू का उपयोग करना है।

  • प्रत्येक पंक्ति के लिए नया डेटाफ़्रेम बनाएं और ...
    • ... इसे जोड़ें (13.0 s)
    • ... इसे संक्षिप्त करें (13.1 s)
  • पहले एक और कंटेनर में सभी नई पंक्तियों को स्टोर करें, एक बार नए डेटाफ़्रेम में परिवर्तित करें और संलग्न करें ...
    • कंटेनर = सूचियों की सूची (2.0 एस)
    • कंटेनर = सूचियों का शब्दकोश (1.9 s)
  • संपूर्ण डेटाफ़्रेम को प्रीलेक्लेट करें, नई पंक्तियों और सभी स्तंभों पर पुनरावृति करें और उपयोग करके भरें
    • ... (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

सू, आपके प्रश्न को NaN को ['x', C] में बदलकर मान 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'])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.