एक पांडा डेटाफ़्रेम में कई कॉलम का चयन करना


1109

मेरे पास विभिन्न स्तंभों में डेटा है, लेकिन मुझे नहीं पता कि इसे दूसरे चर में सहेजने के लिए कैसे निकाला जाए।

index  a   b   c
1      2   3   4
2      3   4   5

मैं कैसे चयन करूं 'a', 'b'और इसे df1 में सहेजूं?

मैंने कोशिश की

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

किसी को काम नहीं लगता।


2
आप कभी भी .ixइसका उपयोग नहीं करना चाहते क्योंकि यह अस्पष्ट है। का उपयोग करें .ilocया .locयदि आप अवश्य करें।
एक्यूमेनस

1
क्या कोई ऐसा तरीका है, जिसे हेडर नामों का उल्लेख किए बिना किया जा सकता है? आर की तरह, मैं इसे इस तरह से कर सकता हूं: > csvtable_imp_1 <- csvtable_imp[0:6]और यह 0 और 6 के बीच पहले कॉलम की डेल्टा राशि का चयन करता है। मुझे केवल यह करना है कि रीड-लिब के साथ सीलबंद के रूप में सीएसवी-टेबल को पढ़ना है।
माइकल 30

मैंने इसके साथ थोड़ा और काम किया है। कुछ वैसा ही मिला, जैसा वह चाहता था। डिफ़ॉल्ट चार नंबर का चयन करना है न कि कॉलम का। infile_1 = largefile_stay.ix[:,0:6]
माइकल

3
इस देर से ठोकर खाने वालों के लिए, ixअब पदावनत कर दिया गया है। पंडों या तो का उपयोग करने की सलाह देते हैं: loc(लेबल-आधारित अनुक्रमण) या iloc(स्थितीय आधारित अनुक्रमण)।
ZaydH

जवाबों:


1767

स्तंभ नाम (जो तार हैं) को आपके द्वारा आजमाए गए तरीके से कटा हुआ नहीं किया जा सकता है।

यहां आपके पास कुछ विकल्प हैं। यदि आप संदर्भ से जानते हैं कि आप किस चर को समाप्त करना चाहते हैं, तो आप केवल सूची में __getitem__वाक्य रचना ([]] को पारित करके केवल उन स्तंभों का एक दृश्य वापस कर सकते हैं ।

df1 = df[['a','b']]

वैकल्पिक रूप से, अगर यह उन्हें संख्यात्मक रूप से अनुक्रमित करने के लिए मायने रखता है न कि उनके नाम से (जैसा कि आपके कोड को स्वचालित रूप से पहले दो कॉलम के नाम को जाने बिना करना चाहिए) तो आप इसके बजाय ऐसा कर सकते हैं:

df1 = df.iloc[:,0:2] # Remember that Python does not slice inclusive of the ending index.

इसके अतिरिक्त, आपको अपने आप को पंडों की वस्तु बनाम उस वस्तु की एक प्रति के विचार से परिचित कराना चाहिए। उपरोक्त विधियों में से पहला वांछित उप-ऑब्जेक्ट (वांछित स्लाइस) की स्मृति में एक नई प्रतिलिपि लौटाएगा।

कभी-कभी, हालांकि, पंडों में अनुक्रमण सम्मेलनों होते हैं जो ऐसा नहीं करते हैं और इसके बजाय आपको एक नया चर देते हैं जो मूल वस्तु में उप-ऑब्जेक्ट या स्लाइस के रूप में स्मृति के एक ही भाग को संदर्भित करता है। यह अनुक्रमण के दूसरे तरीके के साथ होगा, इसलिए आप इसे copy()नियमित कॉपी प्राप्त करने के लिए फ़ंक्शन के साथ संशोधित कर सकते हैं । जब ऐसा होता है, तो आप जो सोचते हैं उसे बदलकर कटा हुआ ऑब्जेक्ट कभी-कभी मूल ऑब्जेक्ट को बदल सकता है। इसके लिए लुक आउट होना हमेशा अच्छा होता है।

df1 = df.iloc[0,0:2].copy() # To avoid the case where changing df1 also changes df

उपयोग करने के लिए iloc, आपको कॉलम पदों (या सूचकांक) को जानना होगा। जैसा कि स्तंभ स्थिति बदल सकती है, हार्ड-कोडिंग सूचकांकों के बजाय, आप कॉलम प्राप्त करने के लिए डेटाफ्रेम ऑब्जेक्ट की विधि के फ़ंक्शन ilocके साथ उपयोग कर सकते हैं ।get_loccolumns

{df.columns.get_loc(c):c for idx, c in enumerate(df.columns)}

अब आप इस शब्दकोश का उपयोग नामों और उपयोग के माध्यम से कॉलम तक पहुंचने के लिए कर सकते हैं iloc


192
नोट: df[['a','b']]एक कॉपी तैयार करता है
वेस मैकिनी

1
हाँ यह मेरे उत्तर में निहित था। ix[]यदि आप किसी भी कारण से उपयोग करना पसंद करते हैं, तो कॉपी के बारे में बिट केवल उपयोग के लिए था ix[]
ईली

1
ixअनुक्रमित पंक्तियाँ, कॉलम नहीं। मुझे लगा कि ओपी को कॉलम चाहिए।
हॉब्स

9
ixस्लाइस तर्कों को स्वीकार करता है, इसलिए आप कॉलम भी प्राप्त कर सकते हैं। उदाहरण के लिए, df.ix[0:2, 0:2]ऊपरी बाएँ 2x2 उप-सरणी को ठीक वैसे ही प्राप्त करता है जैसे यह एक NumPy मैट्रिक्स (आपके कॉलम के नामों के आधार पर) के लिए होता है। आप कॉलम के स्ट्रिंग नामों पर भी स्लाइस सिंटैक्स का उपयोग कर सकते हैं, जैसे df.ix[0, 'Col1':'Col5']। उस सभी कॉलम को प्राप्त होता है जो कि सरणी में Col1और उसके बीच क्रमबद्ध होता है । यह कहना गलत है कि अनुक्रमित पंक्तियाँ। यह सिर्फ इसका सबसे बुनियादी उपयोग है। यह उससे भी अधिक अनुक्रमण का समर्थन करता है। तो, इस प्रश्न के लिए पूरी तरह से सामान्य है। Col5df.columnsixix
ely

7
@AndrewCassidy फिर कभी .ix का उपयोग न करें। यदि आप पूर्णांकों के उपयोग के साथ स्लाइस करना चाहते हैं .ilocजो कि पायथन सूचियों की तरह ही अंतिम स्थिति के लिए विशिष्ट है।
टेड पेट्रो

133

संस्करण 0.11.0 तक, अनुक्रमणिका का उपयोग करके आपके द्वारा आज़माए गए तरीके से स्तंभों को कटा जा सकता है.loc :

df.loc[:, 'C':'E']

के बराबर है

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

और के Cमाध्यम से कॉलम देता है E


एक बेतरतीब ढंग से उत्पन्न DataFrame पर एक डेमो:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)), 
                  columns=list('ABCDEF'), 
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out: 
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

स्तंभों को C से E तक ले जाने के लिए (ध्यान दें कि पूर्णांक स्लाइसिंग के विपरीत, 'E' कॉलम में शामिल है):

df.loc[:, 'C':'E']

Out: 
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

समान लेबल के आधार पर पंक्तियों के चयन के लिए काम करता है। उन स्तंभों से 'R6' को 'R10' तक पंक्तियाँ प्राप्त करें:

df.loc['R6':'R10', 'C':'E']

Out: 
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.locएक बूलियन सरणी को भी स्वीकार करता है ताकि आप उन कॉलम का चयन कर सकें जिनकी सरणी में संबंधित प्रविष्टि है True। उदाहरण के लिए, df.columns.isin(list('BCD'))रिटर्न array([False, True, True, True, False, False], dtype=bool)- सही है यदि सूची में कॉलम का नाम है ['B', 'C', 'D']; झूठा, अन्यथा।

df.loc[:, df.columns.isin(list('BCD'))]

Out: 
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...

110

मान लें कि आपके कॉलम के नाम ( df.columns) हैं ['index','a','b','c'], तो आप जो डेटा चाहते हैं, वह तीसरे और चौथे कॉलम में है। यदि आप अपने नाम नहीं जानते हैं जब आपकी स्क्रिप्ट चलती है, तो आप ऐसा कर सकते हैं

newdf = df[df.columns[2:4]] # Remember, Python is 0-offset! The "3rd" entry is at slot 2.

जैसा कि ईएमएस अपने जवाब में बताते हैं , df.ixस्लाइस कॉलम थोड़ा और अधिक संक्षिप्त रूप से होता है, लेकिन .columnsस्लाइसिंग इंटरफ़ेस अधिक प्राकृतिक हो सकता है क्योंकि यह वेनिला 1-डी पायथन लिस्ट इंडेक्सिंग / स्लाइसिंग सिंटैक्स का उपयोग करता है।

चेतावनी: 'index'एक DataFrameस्तंभ के लिए एक बुरा नाम है । उसी लेबल का उपयोग वास्तविक df.indexविशेषता, एक Indexसरणी के लिए भी किया जाता है । तो आपका कॉलम वापस आ जाता है df['index']और असली डेटाफ्रेम इंडेक्स वापस आ जाता है df.index। एक Indexएक विशेष प्रकार का है Seriesयह तत्वों 'मूल्यों के देखने के लिए अनुकूलित। Df.index के लिए यह उनके लेबल द्वारा पंक्तियों को देखने के लिए है। उनके लेबल द्वारा कॉलम देखने के लिए यह df.columnsविशेषता भी एक pd.Indexसरणी है।


3
जैसा कि मैंने ऊपर मेरी टिप्पणी में बताया गया है, .ixहै सिर्फ पंक्तियों के लिए। यह सामान्य प्रयोजन टुकड़ा करने की क्रिया के लिए है, और इसका उपयोग बहुआयामी टुकड़ा करने की क्रिया के लिए किया जा सकता है। यह मूल रूप से NumPy के सामान्य __getitem__सिंटैक्स का एक इंटरफ़ेस है । उस ने कहा, आप आसानी से एक कॉलम-स्लाइसिंग समस्या को केवल ट्रांसपोज़ ऑपरेशन लागू करके, पंक्ति-स्लाइसिंग समस्या में बदल सकते हैं df.T। आपका उदाहरण उपयोग करता है columns[1:3], जो थोड़ा भ्रामक है। का परिणाम columnsएक है Series; केवल एक सरणी की तरह व्यवहार न करें। साथ ही, आपको columns[2:3]अपनी "तीसरी और चौथी" टिप्पणी के साथ मेल खाने के लिए इसे बदलना चाहिए ।
ely

@ Mr.F: मेरी [2:4]बात सही है। तुम्हारा [2:3]गलत है और एक सीक्वेंस / सीरीज़ बनाने के लिए स्टैंडर्ड पायथन स्लाइस नोटेशन का उपयोग करना IMO को भ्रमित नहीं करता है। लेकिन मुझे आपके डेटा अंतर्निहित इंटरफ़ेस के साथ बाईपास पसंद है ताकि अंतर्निहित सुन्न सरणी तक पहुंच सके ix
hobs

आप इस मामले में सही हैं, लेकिन मैं जिस बिंदु को बनाने की कोशिश कर रहा था, वह यह है कि सामान्य तौर पर, पंडों में लेबल के साथ स्लाइस करना समापन बिंदु (या कम से कम पिछले पंडों के संस्करणों में यही व्यवहार था) में शामिल है। इसलिए यदि आप इसे पुनर्प्राप्त करते हैं df.columnsऔर इसे लेबल द्वारा स्लाइस करना चाहते हैं , तो आपके पास अलग-अलग स्लाइस शब्दार्थ होंगे, यदि आप इसे पूर्णांक अनुक्रमणिका स्थिति द्वारा स्लाइस करते हैं । मैंने निश्चित रूप से अपनी पिछली टिप्पणी में इसे अच्छी तरह से नहीं समझाया था।
एली

आह, अब मैं तुम्हारी बात को देखता हूं। मैं भूल गया कि columnsएक अपरिवर्तनीय श्रृंखला है और सूचक को सूचक के रूप में लेबल का उपयोग करने के लिए ओवरराइड किया गया है। स्पष्ट करने के लिए समय निकालने के लिए धन्यवाद।
हॉब्स

2
नोट: पदावनति चेतावनी: .ix को पदावनत किया जाता है। इसलिए यह समझ में आता है: newdf = df [df.columns [२: ४]]
२३:०४ पर मार्टियन लुब्रिंक

64
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5

1
क्या होगा यदि मैं स्तंभ नाम बदलने के लिए, की तरह उदाहरण के लिए कुछ करना चाहता था: df[['b as foo', 'c as bar']ऐसा है कि उत्पादन स्तंभ का नाम बदलता है bके रूप में fooऔर स्तंभ cके रूप में bar?
कुआनब

5
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
ग्रेग

61

मुझे एहसास है कि यह सवाल काफी पुराना है, लेकिन पांडा के नवीनतम संस्करण में ऐसा करने का एक आसान तरीका है। कॉलम के नाम (जो तार हैं) को आप जिस भी तरीके से पसंद कर सकते हैं।

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)

6
यह केवल सृजन पर किया जा सकता है। सवाल पूछ रहा है कि क्या आपके पास पहले से ही डेटाफ्रेम में है।
बंजोकैट

2
@ बैंजोत, यह मौजूदा
डेटाफ्रेम

23

आप स्तंभों की एक सूची प्रदान की जा सकती है और पांडस DataFrame drop()पर फ़ंक्शन का उपयोग करके आवश्यक कॉलम के साथ DataFrame को वापस कर सकते हैं।

बस केह रहा हू

colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

सिर्फ कॉलम के साथ एक DataFrame लौटाएगा bऔर c

dropविधि प्रलेखित है यहाँ


23

पांडा के साथ,

बुद्धि स्तंभ नाम

dataframe[['column1','column2']]

सूचकांक संख्या के साथ iloc और विशिष्ट कॉलमों का चयन करने के लिए:

dataframe.iloc[:,[1,2]]

स्थानीय स्तंभ नामों के साथ उपयोग किया जा सकता है

dataframe.loc[:,['column1','column2']]


15

0.21.0 के साथ शुरू, एक या अधिक लापता लेबल के साथ एक सूची का उपयोग करके .locया उसके []पक्ष में पदावनत किया जाता है .reindex। तो, आपके प्रश्न का उत्तर है:

df1 = df.reindex(columns=['b','c'])

पूर्व संस्करणों में, का उपयोग .loc[list-of-labels]करना तब तक काम करेगा जब तक कि कुंजियों में से कम से कम 1 पाया गया (अन्यथा यह ए KeyError) बढ़ाएगा । यह व्यवहार हटा दिया गया है और अब एक चेतावनी संदेश दिखाता है। अनुशंसित विकल्प का उपयोग करना है .reindex()

अनुक्रमण और चयन डेटा पर अधिक पढ़ें


10

आप पांडा का उपयोग कर सकते हैं। मैं DataFrame बनाता हूं:

    import pandas as pd
    df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]], 
                      index=['Jane', 'Peter','Alex','Ann'],
                      columns=['Test_1', 'Test_2', 'Test_3'])

डेटाफ़्रेम:

           Test_1  Test_2  Test_3
    Jane        1       2       5
    Peter       5       4       5
    Alex        7       7       8
    Ann         7       6       9

नाम से 1 या अधिक कॉलम चुनने के लिए:

    df[['Test_1','Test_3']]

           Test_1  Test_3
    Jane        1       5
    Peter       5       5
    Alex        7       8
    Ann         7       9

आप भी उपयोग कर सकते हैं:

    df.Test_2

और यो कॉलम मिलता है Test_2

    Jane     2
    Peter    4
    Alex     7
    Ann      6

आप इन पंक्तियों का उपयोग करके कॉलम और पंक्तियों का चयन भी कर सकते हैं .loc()। इसे "स्लाइसिंग" कहा जाता है । सूचना है कि मैं स्तंभ से ले Test_1करने के लिएTest_3

    df.loc[:,'Test_1':'Test_3']

"स्लाइस" है:

            Test_1  Test_2  Test_3
     Jane        1       2       5
     Peter       5       4       5
     Alex        7       7       8
     Ann         7       6       9

और तुम सिर्फ चाहते हैं Peterऔर Annस्तंभों से Test_1और Test_3:

    df.loc[['Peter', 'Ann'],['Test_1','Test_3']]

आपको मिला:

           Test_1  Test_3
    Peter       5       5
    Ann         7       9

8

यदि आप पंक्ति अनुक्रमणिका और स्तंभ नाम से एक तत्व प्राप्त करना चाहते हैं, तो आप इसे वैसे ही कर सकते हैं df['b'][0]। यह उतना ही सरल है जितना आप इमेज कर सकते हैं।

या आप df.ix[0,'b']सूचकांक और लेबल के मिश्रित उपयोग का उपयोग कर सकते हैं ।

नोट: चूंकि v0.20 / के ixपक्ष में पदावनत किया गया है ।lociloc


6

एक अलग और आसान तरीका: पुनरावृत्त पंक्तियाँ

iterows का उपयोग कर

 df1= pd.DataFrame() #creating an empty dataframe
 for index,i in df.iterrows():
    df1.loc[index,'A']=df.loc[index,'A']
    df1.loc[index,'B']=df.loc[index,'B']
    df1.head()

5
कृपया पुनरावृत्तियों () का उपयोग करने की अनुशंसा न करें। यह पंडों के इतिहास में सबसे खराब प्रतिमानों का एक प्रखर प्रलाप है।
cs95

क्या आप कृपया बता सकते हैं कि "सबसे खराब पैटर्न" से आपका क्या मतलब है?
अंकिता

1
पांडा का उपयोग करते समय IMHO, iterrows () अंतिम विकल्प होना चाहिए।
एल्फ

5

उपरोक्त प्रतिक्रियाओं में चर्चा की गई विभिन्न दृष्टिकोण इस धारणा पर आधारित हैं कि या तो उपयोगकर्ता कॉलम इंडिक्स को ड्रॉप या सब्मिट करना जानता है, या उपयोगकर्ता कॉलम की एक सीमा का उपयोग करके डेटाफ़्रेम को कम करना चाहता है (उदाहरण के लिए 'C': 'E') । pandas.DataFrame.drop () निश्चित रूप से उपयोगकर्ता द्वारा परिभाषित किए गए स्तंभों की एक सूची के आधार पर डेटा को कम करने का एक विकल्प है (हालांकि आपको सतर्क रहना होगा कि आप हमेशा डेटाफ़्रेम की प्रतिलिपि का उपयोग करें और inplace पैरामीटर True पर सेट नहीं होना चाहिए !!)

एक अन्य विकल्प pandas.columns.difference () का उपयोग करना है , जो स्तंभ नामों पर एक सेट अंतर करता है, और वांछित स्तंभों वाले एक अनुक्रमणिका प्रकार का सरणी देता है। निम्नलिखित समाधान है:

df = pd.DataFrame([[2,3,4],[3,4,5]],columns=['a','b','c'],index=[1,2])
columns_for_differencing = ['a']
df1 = df.copy()[df.columns.difference(columns_for_differencing)]
print(df1)

उत्पादन होगा: b c 1 3 4 2 4 5


1
प्रतिलिपि () आवश्यक नहीं है। यानी: df1 = df[df.columns.difference(columns_for_differencing)]एक नया / कॉपी किया गया डेटाफ्रेम लौटाएगा। आप df1बिना फेरबदल के संशोधित करने में सक्षम होंगे df। धन्यवाद, btw। यह वही था जो मुझे चाहिए था।
बाजीली डेबोव्स्की

4

आप df.pop () का भी उपयोग कर सकते हैं

>>> df = pd.DataFrame([('falcon', 'bird',    389.0),
...                    ('parrot', 'bird',     24.0),
...                    ('lion',   'mammal',   80.5),
...                    ('monkey', 'mammal', np.nan)],
...                   columns=('name', 'class', 'max_speed'))
>>> df
     name   class  max_speed
0  falcon    bird      389.0
1  parrot    bird       24.0
2    lion  mammal       80.5
3  monkey  mammal 

>>> df.pop('class')
0      bird
1      bird
2    mammal
3    mammal
Name: class, dtype: object

>>> df
     name  max_speed
0  falcon      389.0
1  parrot       24.0
2    lion       80.5
3  monkey        NaN

मुझे बताएं कि क्या यह आपके लिए मदद करता है, कृपया df.pop (c) का उपयोग करें


3

मैंने उस पर कई उत्तर देखे हैं, लेकिन मेरे लिए अस्पष्ट रहा। आप ब्याज के उन कॉलमों का चयन कैसे करेंगे? इसका उत्तर यह है कि यदि आप उन्हें किसी सूची में एकत्र कर चुके हैं, तो आप सूची का उपयोग करके कॉलम को संदर्भित कर सकते हैं।

उदाहरण

print(extracted_features.shape)
print(extracted_features)

(63,)
['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
 'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
 'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
 'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
 'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
 'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
 'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
 'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
 'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']

मेरे पास निम्न सूची / संख्या है extracted_features, जिसमें 63 कॉलम निर्दिष्ट हैं। मूल डेटासेट में 103 कॉलम हैं, और मैं वास्तव में उन्हें निकालना चाहता हूं, फिर मैं उपयोग करूंगा

dataset[extracted_features]

और आप इसे खत्म कर देंगे

यहां छवि विवरण दर्ज करें

यह कुछ आप मशीन लर्निंग में (अक्सर विशेष रूप से, सुविधा चयन में) का उपयोग करेंगे। मैं अन्य तरीकों पर भी चर्चा करना चाहूंगा, लेकिन मुझे लगता है कि यह पहले से ही अन्य स्टैकओवरफ्लॉवर द्वारा कवर किया गया है। आशा है कि यह उपयोगी रहा है!


1

आप pandas.DataFrame.filterइस तरह से या तो स्तंभों को फ़िल्टर या फिर से करने के लिए विधि का उपयोग कर सकते हैं :

df1 = df.filter(['a', 'b'])

0
df[['a','b']] # select all rows of 'a' and 'b'column 
df.loc[0:10, ['a','b']] # index 0 to 10 select column 'a' and 'b'
df.loc[0:10, ['a':'b']] # index 0 to 10 select column 'a' to 'b'
df.iloc[0:10, 3:5] # index 0 to 10 and column 3 to 5
df.iloc[3, 3:5] # index 3 of column 3 to 5
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.