पांडा: उन सभी स्तंभों का चयन करने का सबसे अच्छा तरीका जिनके नाम X से शुरू होते हैं


104

मेरे पास डेटाफ़्रेम है:

import pandas as pd
import numpy as np

df = pd.DataFrame({'foo.aa': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
                   'foo.fighters': [0, 1, np.nan, 0, 0, 0],
                   'foo.bars': [0, 0, 0, 0, 0, 1],
                   'bar.baz': [5, 5, 6, 5, 5.6, 6.8],
                   'foo.fox': [2, 4, 1, 0, 0, 5],
                   'nas.foo': ['NA', 0, 1, 0, 0, 0],
                   'foo.manchu': ['NA', 0, 0, 0, 0, 0],})

मैं शुरू होने वाले कॉलमों में 1 के मूल्यों का चयन करना चाहता हूं foo.। क्या इसके अलावा इसे करने का एक बेहतर तरीका है:

df2 = df[(df['foo.aa'] == 1)|
(df['foo.fighters'] == 1)|
(df['foo.bars'] == 1)|
(df['foo.fox'] == 1)|
(df['foo.manchu'] == 1)
]

कुछ लिखने जैसा है:

df2= df[df.STARTS_WITH_FOO == 1]

जवाब इस तरह एक DataFrame प्रिंट करना चाहिए:

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

[4 rows x 7 columns]

जवाबों:


151

अपने कॉलम बनाने के लिए बस एक सूची समझने की क्रिया करें:

In [28]:

filter_col = [col for col in df if col.startswith('foo')]
filter_col
Out[28]:
['foo.aa', 'foo.bars', 'foo.fighters', 'foo.fox', 'foo.manchu']
In [29]:

df[filter_col]
Out[29]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

एक अन्य विधि स्तंभों से एक श्रृंखला बनाना और सदिश स्ट्रेट विधि का उपयोग करना है startswith:

In [33]:

df[df.columns[pd.Series(df.columns).str.startswith('foo')]]
Out[33]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

आप जो चाहते हैं उसे प्राप्त करने के लिए आपको उन मानों को फ़िल्टर करने के लिए निम्नलिखित जोड़ने की आवश्यकता है जो आपके ==1मानदंडों को पूरा नहीं करते हैं:

In [36]:

df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]]==1]
Out[36]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      NaN       1       NaN           NaN      NaN        NaN     NaN
1      NaN     NaN       NaN             1      NaN        NaN     NaN
2      NaN     NaN       NaN           NaN        1        NaN     NaN
3      NaN     NaN       NaN           NaN      NaN        NaN     NaN
4      NaN     NaN       NaN           NaN      NaN        NaN     NaN
5      NaN     NaN         1           NaN      NaN        NaN     NaN

संपादित करें

यह देखने के बाद कि आप क्या उत्तर चाहते हैं, ठीक है:

In [72]:

df.loc[df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]] == 1].dropna(how='all', axis=0).index]
Out[72]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

66

अब जब पांडा के इंडेक्स स्ट्रिंग ऑपरेशन का समर्थन करते हैं, तो निश्चित रूप से 'फू' से शुरू होने वाले कॉलम का चयन करने का सबसे सरल और सबसे अच्छा तरीका है:

df.loc[:, df.columns.str.startswith('foo')]

वैकल्पिक रूप से, आप कॉलम (या पंक्ति) लेबल को फ़िल्टर कर सकते हैं df.filter()। नामों से मेल खाने के लिए एक नियमित अभिव्यक्ति निर्दिष्ट करने के लिए foo.:

>>> df.filter(regex=r'^foo\.', axis=1)
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

केवल आवश्यक पंक्तियों (युक्त 1) और locकॉलमों का चयन करने के लिए , आप filter(या किसी भी अन्य विधि) का उपयोग करके और पंक्तियों का चयन करके उपयोग कर सकते हैं any:

>>> df.loc[(df == 1).any(axis=1), df.filter(regex=r'^foo\.', axis=1).columns]
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0


1

@ EdChum के उत्तर के आधार पर, आप निम्न समाधान आज़मा सकते हैं:

df[df.columns[pd.Series(df.columns).str.contains("foo")]]

यह उन मामलों में वास्तव में मददगार होगा जब आप उन सभी स्तंभों का चयन नहीं करते हैं, जिनके साथ आप प्रारंभ करना चाहते हैं foo। यह विधि उन सभी स्तंभों का चयन करती है जिनमें सबस्ट्रिंग होते हैं fooऔर इसे किसी स्तंभ के नाम के किसी भी बिंदु पर रखा जा सकता है।

संक्षेप में, मैंने .startswith()साथ दिया .contains()


0

मेरा समाधान। यह प्रदर्शन पर धीमा हो सकता है:

a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith('foo'))
a.sort_index()


   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

इच्छित प्रविष्टियों के चयन के लिए एक और विकल्प का उपयोग करना है map:

df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith('foo'))]

जो आपको उन पंक्तियों के लिए सभी कॉलम देता है जिनमें 1निम्न शामिल हैं :

   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0

पंक्ति चयन द्वारा किया जाता है

(df == 1).any(axis=1)

@ @ ajcr के जवाब में जो आपको देता है:

0     True
1     True
2     True
3    False
4    False
5     True
dtype: bool

अर्थ है कि पंक्ति 3और4 एक शामिल नहीं है 1और चयनित नहीं किया जाएगा।

स्तंभों का चयन इस तरह बूलियन अनुक्रमण का उपयोग किया जाता है:

df.columns.map(lambda x: x.startswith('foo'))

इस रिटर्न के ऊपर के उदाहरण में

array([False,  True,  True,  True,  True,  True, False], dtype=bool)

तो, अगर एक कॉलम के साथ शुरू नहीं होता है foo , तो Falseउसे लौटा दिया जाता है और इसलिए कॉलम का चयन नहीं किया जाता है।

यदि आप केवल उन सभी पंक्तियों को वापस करना चाहते हैं जिनमें एक 1- जैसा कि आपका वांछित आउटपुट बताता है - आप बस कर सकते हैं

df.loc[(df == 1).any(axis=1)]

जो लौटता है

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

"फू" से शुरू होने वाले कॉलम को फ़िल्टर करने के लिए आप यहां रेगेक्स को आजमा सकते हैं

df.filter(regex='^foo*')

यदि आपको अपने कॉलम में स्ट्रिंग फू की आवश्यकता है तो

df.filter(regex='foo*')

उचित होगा।

अगले चरण के लिए, आप उपयोग कर सकते हैं

df[df.filter(regex='^foo*').values==1]

उन पंक्तियों को फ़िल्टर करने के लिए जहाँ 'foo *' कॉलम का मान 1 है।


0

मेरे मामले में मुझे उपसर्गों की एक सूची की आवश्यकता थी

colsToScale=["production", "test", "development"]
dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.