दो पंडों के स्तंभों का स्ट्रिंग संयोजन


84

मेरे पास निम्नलिखित हैं DataFrame:

from pandas import *
df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3]})

यह इस तरह दिख रहा है:

    bar foo
0    1   a
1    2   b
2    3   c

अब मैं कुछ ऐसा करना चाहता हूं:

     bar
0    1 is a
1    2 is b
2    3 is c

इसे कैसे प्राप्त किया जा सकता है? मैंने निम्नलिखित कोशिश की:

df['foo'] = '%s is %s' % (df['bar'], df['foo'])

लेकिन यह मुझे एक गलत परिणाम देता है:

>>>print df.ix[0]

bar                                                    a
foo    0    a
1    b
2    c
Name: bar is 0    1
1    2
2
Name: 0

गूंगे प्रश्न के लिए क्षमा करें, लेकिन यह एक पांडा: एक DataFrame में दो कॉलम गठबंधन मेरे लिए उपयोगी नहीं था।

जवाबों:



65

इस सवाल का जवाब पहले ही दिया जा चुका है, लेकिन मेरा मानना ​​है कि कुछ उपयोगी तरीकों को पहले से ही मिश्रण में चर्चा नहीं करना अच्छा होगा, और प्रदर्शन के मामले में प्रस्तावित सभी तरीकों की तुलना करें।

प्रदर्शन के बढ़ते क्रम में, इस समस्या के कुछ उपयोगी समाधान दिए गए हैं।


DataFrame.agg

यह एक साधारण- str.formatआधारित दृष्टिकोण है।

df['baz'] = df.agg('{0[bar]} is {0[foo]}'.format, axis=1)
df
  foo  bar     baz
0   a    1  1 is a
1   b    2  2 is b
2   c    3  3 is c

आप यहां एफ-स्ट्रिंग फॉर्मेटिंग का भी उपयोग कर सकते हैं:

df['baz'] = df.agg(lambda x: f"{x['bar']} is {x['foo']}", axis=1)
df
  foo  bar     baz
0   a    1  1 is a
1   b    2  2 is b
2   c    3  3 is c

char.array-बेड कॉनटैशन

कॉलम को रूपांतरित करने के लिए रूपांतरित करें chararrays, फिर उन्हें एक साथ जोड़ें।

a = np.char.array(df['bar'].values)
b = np.char.array(df['foo'].values)

df['baz'] = (a + b' is ' + b).astype(str)
df
  foo  bar     baz
0   a    1  1 is a
1   b    2  2 is b
2   c    3  3 is c

के साथ सूची की समझzip

मैं यह नहीं समझ सकता कि पैंडों में अंडररेटेड सूची की समझ कैसे है।

df['baz'] = [str(x) + ' is ' + y for x, y in zip(df['bar'], df['foo'])]

वैकल्पिक रूप से, str.joinकॉनकैट का उपयोग करना (बेहतर पैमाने भी होगा):

df['baz'] = [
    ' '.join([str(x), 'is', y]) for x, y in zip(df['bar'], df['foo'])]

df
  foo  bar     baz
0   a    1  1 is a
1   b    2  2 is b
2   c    3  3 is c

स्ट्रिंग हेरफेर में एक्सक्लूसिव कॉन्ट्रैक्ट्स की सूची, क्योंकि स्ट्रिंग ऑपरेशंस को वेक्टराइज़ करना कठिन है, और ज्यादातर पांडा "वेक्टराइज्ड" फ़ंक्शन मूल रूप से लूप्स के आसपास के रैपर हैं। मैंने इस विषय के बारे में विस्तार से लिखा है कि फॉर लूप्स इन पंडों के साथ - मुझे कब ध्यान देना चाहिए? । सामान्य तौर पर, यदि आपको सूचकांक संरेखण के बारे में चिंता करने की आवश्यकता नहीं है, तो स्ट्रिंग और रेगेक्स संचालन से निपटने के लिए एक सूची समझ का उपयोग करें।

डिफ़ॉल्ट रूप से ऊपर दी गई सूची NaN को हैंडल नहीं करती है। हालाँकि, आप हमेशा एक कोशिश को लपेटकर एक फ़ंक्शन लिख सकते हैं-अगर आपको इसे संभालने की आवश्यकता हो, तो।

def try_concat(x, y):
    try:
        return str(x) + ' is ' + y
    except (ValueError, TypeError):
        return np.nan


df['baz'] = [try_concat(x, y) for x, y in zip(df['bar'], df['foo'])]

perfplot प्रदर्शन माप

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

परफ्लोट का उपयोग करके उत्पन्न ग्राफ । यहाँ पूरी कोड सूची दी गई है

कार्य

def brenbarn(df):
    return df.assign(baz=df.bar.map(str) + " is " + df.foo)

def danielvelkov(df):
    return df.assign(baz=df.apply(
        lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1))

def chrimuelle(df):
    return df.assign(
        baz=df['bar'].astype(str).str.cat(df['foo'].values, sep=' is '))

def vladimiryashin(df):
    return df.assign(baz=df.astype(str).apply(lambda x: ' is '.join(x), axis=1))

def erickfis(df):
    return df.assign(
        baz=df.apply(lambda x: f"{x['bar']} is {x['foo']}", axis=1))

def cs1_format(df):
    return df.assign(baz=df.agg('{0[bar]} is {0[foo]}'.format, axis=1))

def cs1_fstrings(df):
    return df.assign(baz=df.agg(lambda x: f"{x['bar']} is {x['foo']}", axis=1))

def cs2(df):
    a = np.char.array(df['bar'].values)
    b = np.char.array(df['foo'].values)

    return df.assign(baz=(a + b' is ' + b).astype(str))

def cs3(df):
    return df.assign(
        baz=[str(x) + ' is ' + y for x, y in zip(df['bar'], df['foo'])])

4
यही सब मैं हमेशा पंडों में स्ट्रिंग के बारे में जानना चाहता था, लेकिन बहुत डर भी रहा था!
15

क्या आप कृपया प्लॉट को अगले स्तर १० ४ (या इससे भी अधिक) पर अपडेट कर सकते हैं , १० ३ (१००० जो आज की स्थिति के लिए बहुत छोटा है) तक सीमित प्लॉट के साथ एक त्वरित दृश्य उत्तर है कि cs3 सबसे अच्छा है, अंततः जब आप देखते हैं brenbarn cs3 की तुलना में कम घातीय लग रहा है, इसलिए संभवतः बड़े डेटासेट के लिए brenbarn सबसे अच्छा (तेज) उत्तर है।
वेलिजर वेसलिनोव

1
@VelizarVESSELINOV अपडेट किया गया! मेरे लिए आश्चर्य की बात यह है कि सूची संकलन और पंडों के सम्मेलन की तुलना में सुन्न अवतलन धीमा है।
CS95

1
आप उपयोग कर विचार किया है df['bar'].tolist()और df['foo'].tolist()में cs3()? मेरा अनुमान है कि यह "आधार" समय को थोड़ा बढ़ाएगा लेकिन यह बेहतर होगा।
छायाकार

44

आपके कोड में समस्या यह है कि आप हर पंक्ति पर ऑपरेशन को लागू करना चाहते हैं। जिस तरह से आपने इसे लिखा है, हालांकि पूरे 'बार' और 'फू' कॉलम को लेता है, उन्हें स्ट्रिंग में कनवर्ट करता है और आपको एक बड़ा स्ट्रिंग वापस देता है। आप इसे लिख सकते हैं:

df.apply(lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1)

यह अन्य उत्तर की तुलना में लंबा है लेकिन अधिक सामान्य है (इसका उपयोग उन मानों के साथ किया जा सकता है जो तार नहीं हैं)।


13

आप भी इस्तेमाल कर सकते हैं

df['bar'] = df['bar'].str.cat(df['foo'].values.astype(str), sep=' is ')

1
यह काम नहीं करता है क्योंकि df ['bar'] एक स्ट्रिंग कॉलम नहीं है। सही काम है df['bar'] = df['bar'].astype(str).str.cat(df['foo'], sep=' is ')
cbrnr

8
df.astype(str).apply(lambda x: ' is '.join(x), axis=1)

0    1 is a
1    2 is b
2    3 is c
dtype: object

यह उत्तर कॉलम की अनिर्धारित संख्या (> 1) और अनिर्धारित कॉलम नामों के साथ भी काम करता है, जो इसे बाकी की तुलना में अधिक उपयोगी बनाता है।
जॉनडैंगर

4

@DanielVelkov का जवाब उचित है, लेकिन स्ट्रिंग व्रत का उपयोग करने वाला BUT तेज़ है:

# Daniel's
%timeit df.apply(lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1)
## 963 µs ± 157 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# String literals - python 3
%timeit df.apply(lambda x: f"{x['bar']} is {x['foo']}", axis=1)
## 849 µs ± 4.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

4

series.str.cat इस समस्या से निपटने का सबसे लचीला तरीका है:

के लिये df = pd.DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3]})

df.foo.str.cat(df.bar.astype(str), sep=' is ')

>>>  0    a is 1
     1    b is 2
     2    c is 3
     Name: foo, dtype: object

या

df.bar.astype(str).str.cat(df.foo, sep=' is ')

>>>  0    1 is a
     1    2 is b
     2    3 is c
     Name: bar, dtype: object

सबसे महत्वपूर्ण (और विपरीत .join()), यह आपको पैरामीटर के Nullसाथ मूल्यों को अनदेखा करने या बदलने की अनुमति देता है na_rep


यह कार्यक्षमता .join()मुझे भ्रमित क्यों नहीं कर रही है
जॉनडैंगर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.