python - पांडा में कॉलम का नाम बदलना




pandas replace dataframe rename (21)

जैसा कि http://pandas.pydata.org/pandas-docs/stable/text.html में प्रलेखित है:

df.columns = df.columns.str.replace('$','')

मेरे पास पांडा और कॉलम लेबल का उपयोग करके डेटाफ्रेम है जिसे मुझे मूल कॉलम लेबल को प्रतिस्थापित करने के लिए संपादित करने की आवश्यकता है।

मैं डेटाफ्रेम A में कॉलम नामों को बदलना चाहता हूं जहां मूल कॉलम नाम हैं:

['$a', '$b', '$c', '$d', '$e'] 

सेवा मेरे

['a', 'b', 'c', 'd', 'e'].

मेरे पास संपादित कॉलम नाम एक सूची में संग्रहीत हैं, लेकिन मुझे नहीं पता कि कॉलम नामों को कैसे बदला जाए।


df = df.rename(columns=lambda n: n.replace('$', ''))

इसे हल करने का एक कार्यात्मक तरीका है


बस इसे .columns विशेषता को असाइन करें:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20

ध्यान दें कि ये दृष्टिकोण मल्टीइंडेक्स के लिए काम नहीं करते हैं। मल्टीइंडेक्स के लिए, आपको निम्न की तरह कुछ करने की आवश्यकता है:

>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
>>> df
   $a $b  e
   $x $y  f
0  1  3  5
1  2  4  6
>>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')}
>>> df.columns = pandas.MultiIndex.from_tuples([
        rename.get(item, item) for item in df.columns.tolist()])
>>> df
   a  b  e
   x  y  f
0  1  3  5
1  2  4  6

यदि आपके पास डेटाफ्रेम है, तो df.columns सबकुछ उस सूची में डंप करता है जिसे आप जोड़ सकते हैं और फिर कॉलम के नाम के रूप में अपने डेटाफ्रेम में फिर से असाइन कर सकते हैं ...

columns = df.columns
columns = [row.replace("$","") for row in columns]
df.rename(columns=dict(zip(columns, things)), inplace=True)
df.head() #to validate the output

सबसे अच्छा तरीका? IDK। एक रास्ता - हाँ।

सवाल के जवाब में आगे रखी गई सभी मुख्य तकनीकों का मूल्यांकन करने का एक बेहतर तरीका सीपीरोफाइल का उपयोग करके गेज मेमोरी और निष्पादन समय तक है। @kadee, @kaitlyn, और @eumiro के पास सबसे तेज़ निष्पादन समय के साथ कार्य था - हालांकि ये कार्य इतनी तेजी से हैं कि हम सभी उत्तरों के लिए .000 और .001 सेकंड के गोलाकार की तुलना कर रहे हैं। नैतिक: संभवतः मेरा उत्तर 'सर्वश्रेष्ठ' तरीका नहीं है।

import pandas as pd
import cProfile, pstats, re

old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'}

df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']})

df.head()

def eumiro(df,nn):
    df.columns = nn
    #This direct renaming approach is duplicated in methodology in several other answers: 
    return df

def lexual1(df):
    return df.rename(columns=col_dict)

def lexual2(df,col_dict):
    return df.rename(columns=col_dict, inplace=True)

def Panda_Master_Hayden(df):
    return df.rename(columns=lambda x: x[1:], inplace=True)

def paulo1(df):
    return df.rename(columns=lambda x: x.replace('$', ''))

def paulo2(df):
    return df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

def migloo(df,on,nn):
    return df.rename(columns=dict(zip(on, nn)), inplace=True)

def kadee(df):
    return df.columns.str.replace('$','')

def awo(df):
    columns = df.columns
    columns = [row.replace("$","") for row in columns]
    return df.rename(columns=dict(zip(columns, '')), inplace=True)

def kaitlyn(df):
    df.columns = [col.strip('$') for col in df.columns]
    return df

print 'eumiro'
cProfile.run('eumiro(df,new_names)')
print 'lexual1'
cProfile.run('lexual1(df)')
print 'lexual2'
cProfile.run('lexual2(df,col_dict)')
print 'andy hayden'
cProfile.run('Panda_Master_Hayden(df)')
print 'paulo1'
cProfile.run('paulo1(df)')
print 'paulo2'
cProfile.run('paulo2(df)')
print 'migloo'
cProfile.run('migloo(df,old_names,new_names)')
print 'kadee'
cProfile.run('kadee(df)')
print 'awo'
cProfile.run('awo(df)')
print 'kaitlyn'
cProfile.run('kaitlyn(df)')

df.rename() तरीका एक फ़ंक्शन ले सकता है, उदाहरण के लिए:

In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)

In [12]: df.rename(columns=lambda x: x[1:], inplace=True)

In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)

मुझे लगता है कि यह विधि उपयोगी है:

df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})

यह विधि आपको कॉलम नामों को व्यक्तिगत रूप से बदलने की अनुमति देती है।


df.rename() फ़ंक्शन का उपयोग करें और कॉलम का नाम बदलकर देखें। सभी कॉलम का नाम बदलना नहीं है:

df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
# Or rename the existing DataFrame (rather than creating a copy) 
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)

डेटाफ्रेम - df.rename () काम करेगा।

df.rename(columns = {'Old Name':'New Name'})

डीएफ आपके पास डेटाफ्रेम है, और पुराना नाम वह कॉलम नाम है जिसे आप बदलना चाहते हैं, फिर नया नाम वह नया नाम है जिसे आप बदलते हैं। यह डेटाफ्रेम अंतर्निहित विधि चीजों को बहुत आसान बनाता है।


इसे इस्तेमाल करे। इससे मेरा काम बनता है

df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})

यदि आपको अपने नियंत्रण से बाहर प्रणाली प्रदान करने वाले कॉलम के भार से निपटना है, तो मैं निम्नलिखित दृष्टिकोण के साथ आया हूं जो एक सामान्य दृष्टिकोण और विशिष्ट प्रतिस्थापन का संयोजन है।

मैं पहले कॉलम नामों के कुछ परिशिष्टों को फेंकने के लिए रेगेक्स अभिव्यक्तियों का उपयोग करके डेटाफ्रेम कॉलम नामों से एक शब्दकोश बनाता हूं और फिर मैं प्राप्तकर्ता डेटाबेस में बाद में कोर कॉलम नाम देने के लिए शब्दकोश में विशिष्ट प्रतिस्थापन जोड़ता हूं।

इसके बाद डेटाफ्रेम पर एक बार में लागू किया जाता है।

dict=dict(zip(df.columns,df.columns.str.replace('(:S$|:C1$|:L$|:D$|\.Serial:L$)','')))
dict['brand_timeseries:C1']='BTS'
dict['respid:L']='RespID'
dict['country:C1']='CountryID
dict['pim1:D']='pim_actual'
df.rename(columns=dict, inplace=True)

df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

यदि कॉलम की आपकी नई सूची मौजूदा कॉलम के समान क्रम में है, असाइनमेंट सरल है:

new_cols = ['a', 'b', 'c', 'd', 'e']
df.columns = new_cols
>>> df
   a  b  c  d  e
0  1  1  1  1  1

यदि आपके पास पुराने कॉलम नामों पर नए कॉलम नामों के लिए एक शब्दकोश कुंजीपटल था, तो आप निम्न कार्य कर सकते हैं:

d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}
df.columns = df.columns.map(lambda col: d[col])  # Or `.map(d.get)` as pointed out by @PiRSquared.
>>> df
   a  b  c  d  e
0  1  1  1  1  1

यदि आपके पास कोई सूची या शब्दकोश मैपिंग नहीं है, तो आप सूची समझ के माध्यम से अग्रणी $ प्रतीक को पट्टी कर सकते हैं:

df.columns = [col[1:] if col[0] == '$' else col for col in df]

चूंकि आप केवल सभी कॉलम नामों में $ साइन को हटाना चाहते हैं, तो आप बस ऐसा कर सकते हैं:

df = df.rename(columns=lambda x: x.replace('$', ''))

या

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

आप इसके लिए str.slice उपयोग कर सकते हैं:

df.columns = df.columns.str.slice(1)

यदि आप पंक्ति नाम df.columns = ['a', 'b',index=False]


कॉलम नाम बनाम श्रृंखला के नाम

मैं दृश्यों के पीछे क्या होता है, इसकी व्याख्या करना चाहता हूं।

डेटाफ्रेम श्रृंखला का एक सेट है।

बदले में श्रृंखला एक numpy.array का विस्तार है

numpy.array पास एक संपत्ति है .name

यह श्रृंखला का नाम है। यह शायद ही कभी है कि पांडा इस विशेषता का सम्मान करते हैं, लेकिन यह जगहों पर आते हैं और कुछ पांडा व्यवहारों को हैक करने के लिए इस्तेमाल किया जा सकता है।

स्तंभों की सूची का नामकरण

यहां बहुत सारे उत्तर df.columns विशेषता के बारे में बात करते हैं, जब वास्तव में यह एक Series । इसका मतलब है कि इसमें एक .name विशेषता है।

यदि आप कॉलम का नाम भरने का निर्णय लेते हैं तो यह होता है:

df.columns = ['column_one', 'column_two']
df.columns.names = ['name of the list of columns']
df.index.names = ['name of the index']

name of the list of columns     column_one  column_two
name of the index       
0                                    4           1
1                                    5           2
2                                    6           3

ध्यान दें कि इंडेक्स का नाम हमेशा एक कॉलम कम आता है।

कलाकृतियों जो रेंगते हैं

कई बार .name विशेषता .name । यदि आप df.columns = ['one', 'two'] तो df.one.name 'one'

यदि आप df.one.name = 'three' सेट df.one.name = 'three' तो df.columns आपको अभी भी ['one', 'two'] , और df.one.name आपको 'three'

परंतु

pd.DataFrame(df.one) वापस आ जाएगा

    three
0       1
1       2
2       3

क्योंकि पांडा पहले से परिभाषित Series के .name का .name उपयोग करते हैं।

मल्टी लेवल कॉलम नाम

पांडों के पास बहु स्तरित कॉलम नाम करने के तरीके हैं। इसमें इतना जादू शामिल नहीं है लेकिन मैं इसे अपने उत्तर में भी कवर करना चाहता था क्योंकि मुझे यह देखने में कोई भी नहीं दिख रहा है।

    |one            |
    |one      |two  |
0   |  4      |  1  |
1   |  5      |  2  |
2   |  6      |  3  |

यह सूची में कॉलम सेट करके आसानी से प्राप्त किया जा सकता है, इस तरह:

df.columns = [['one', 'one'], ['one', 'two']]

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

मेरी विधि सामान्य है जिसमें आप कम से कम delimiters= चर और भविष्य के सबूत को अलग करने के अल्पविराम जोड़ सकते हैं।

कार्य कोड:

import pandas as pd
import re


df = pd.DataFrame({'$a':[1,2], '$b': [3,4],'$c':[5,6], '$d': [7,8], '$e': [9,10]})

delimiters = '$'
matchPattern = '|'.join(map(re.escape, delimiters))
df.columns = [re.split(matchPattern, i)[1] for i in df.columns ]

आउटपुट:

>>> df
   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

>>> df
   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

df.columns = ['a', 'b', 'c', 'd', 'e']

आपके द्वारा प्रदान किए गए क्रम में, आपके द्वारा प्रदान किए गए नामों के साथ मौजूदा नामों को प्रतिस्थापित कर दिया जाएगा।

आप उन्हें इंडेक्स द्वारा भी असाइन कर सकते हैं:

df.columns.values[2] = 'c'    #renames the 2nd column to 'c' (in position #3)

मूल कॉलम लेबल को प्रतिस्थापित करने का एक और तरीका मूल स्तंभ लेबल से अवांछित वर्ण (यहां '$') को अलग करना है।

यह df.columns पर लूप चलाने और df.columns को पट्टी वाले कॉलम को जोड़कर किया जा सकता था।

इसके बजाए, हम नीचे दी गई सूची समझ का उपयोग करके एक ही कथन में यह अच्छी तरह से कर सकते हैं:

df.columns = [col.strip('$') for col in df.columns]

(पायथन में strip विधि स्ट्रिंग के आरंभ और अंत से दिए गए चरित्र को स्ट्रिप्स करती है।)


एक लाइन या पाइपलाइन समाधान

मैं दो चीजों पर ध्यान केंद्रित करूंगा:

  1. ओपी स्पष्ट रूप से बताता है

    मेरे पास संपादित कॉलम नाम एक सूची में संग्रहीत हैं, लेकिन मुझे नहीं पता कि कॉलम नामों को कैसे बदला जाए।

    मैं '$' को प्रतिस्थापित करने या प्रत्येक कॉलम हेडर के पहले वर्ण को बंद करने की समस्या को हल नहीं करना चाहता हूं। ओपी पहले से ही यह कदम उठा चुका है। इसके बजाय मैं मौजूदा columns ऑब्जेक्ट को प्रतिस्थापन कॉलम नामों की एक सूची के साथ एक नए के साथ बदलने पर ध्यान केंद्रित करना चाहता हूं।

  2. df.columns = new जहां new कॉलम नामों की सूची नई है जितनी सरल हो जाती है। इस दृष्टिकोण की कमी यह है कि इसे मौजूदा डेटाफ्रेम के columns विशेषता को संपादित करने की आवश्यकता है और यह इनलाइन नहीं किया गया है। मैं मौजूदा डेटा फ्रेम को संपादित किए बिना पाइपलाइनिंग के माध्यम से इसे करने के कुछ तरीके दिखाऊंगा।

सेटअप 1
पूर्व-मौजूदा सूची के साथ कॉलम नामों को प्रतिस्थापित करने की आवश्यकता पर ध्यान केंद्रित करने के लिए, मैं प्रारंभिक कॉलम नामों और असंबंधित नए कॉलम नामों के साथ एक नया नमूना डेटाफ्रेम df तैयार करूंगा।

df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]})
new = ['x098', 'y765', 'z432']

df

   Jack  Mahesh  Xin
0     1       3    5
1     2       4    6

समाधान 1
pd.DataFrame.rename

यह पहले से ही कहा गया है कि यदि आपके पास पुराने कॉलम नामों को नए कॉलम नामों में मैपिंग करने वाला शब्दकोश था, तो आप pd.DataFrame.rename उपयोग कर सकते हैं।

d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
df.rename(columns=d)

   x098  y765  z432
0     1     3     5
1     2     4     6

हालांकि, आप आसानी से उस शब्दकोश को बना सकते हैं और इसे rename लिए कॉल में शामिल कर सकते हैं। निम्नलिखित इस तथ्य का लाभ उठाते हैं कि जब df पर पुनरावृत्ति होती है, तो हम प्रत्येक कॉलम नाम पर फिर से सक्रिय होते हैं।

# given just a list of new column names
df.rename(columns=dict(zip(df, new)))

   x098  y765  z432
0     1     3     5
1     2     4     6

यदि आपके मूल कॉलम नाम अद्वितीय हैं तो यह बहुत अच्छा काम करता है। लेकिन अगर वे नहीं हैं, तो यह टूट जाता है।

सेटअप 2
गैर अद्वितीय कॉलम

df = pd.DataFrame(
    [[1, 3, 5], [2, 4, 6]],
    columns=['Mahesh', 'Mahesh', 'Xin']
)
new = ['x098', 'y765', 'z432']

df

   Mahesh  Mahesh  Xin
0       1       3    5
1       2       4    6

समाधान 2
keys तर्क का उपयोग कर pd.concat

सबसे पहले, ध्यान दें कि जब हम समाधान 1 का उपयोग करने का प्रयास करते हैं तो क्या होता है:

df.rename(columns=dict(zip(df, new)))

   y765  y765  z432
0     1     3     5
1     2     4     6

हमने कॉलम नाम के रूप में new सूची को मैप नहीं किया। हम y765 दोहराया समाप्त हो गया। इसके बजाए, हम df के कॉलम के माध्यम से pd.concat फ़ंक्शन की keys तर्क का उपयोग कर सकते हैं।

pd.concat([c for _, c in df.items()], axis=1, keys=new) 

   x098  y765  z432
0     1     3     5
1     2     4     6

समाधान 3
फिर से संगठित। इसका उपयोग केवल तभी किया जाना चाहिए जब आपके पास सभी कॉलम के लिए एक ही प्रकार का dtype । अन्यथा, आप सभी कॉलम के लिए dtype object साथ समाप्त हो dtype और उन्हें वापस परिवर्तित करने के लिए और अधिक शब्दकोश काम की आवश्यकता होगी।

एकल dtype

pd.DataFrame(df.values, df.index, new)

   x098  y765  z432
0     1     3     5
1     2     4     6

मिश्रित dtype

pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

समाधान 4
यह transpose और set_index साथ एक set_index चाल है। pd.DataFrame.set_index हमें एक इंडेक्स इनलाइन सेट करने की अनुमति देता है लेकिन कोई संबंधित set_columns । तो हम set_index कर सकते हैं, फिर set_index , और वापस set_index कर सकते हैं। हालांकि, समाधान 3 से मिश्रित dtype dtype बनाम एक ही एकल प्रकार dtype यहां लागू होता है।

एकल dtype

df.T.set_index(np.asarray(new)).T

   x098  y765  z432
0     1     3     5
1     2     4     6

मिश्रित dtype

df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

समाधान 5
pd.DataFrame.rename में एक lambda प्रयोग करें जो new तत्व के प्रत्येक चक्र के माध्यम से चक्र
इस समाधान में, हम एक लैम्ब्डा पास करते हैं जो x लेता है लेकिन फिर इसे अनदेखा करता है। यह एक y भी लेता है लेकिन इसकी उम्मीद नहीं करता है। इसके बजाए, एक इटरेटर को डिफ़ॉल्ट मान के रूप में दिया जाता है और फिर मैं उस समय एक के माध्यम से एक के माध्यम से चक्र के लिए x के मूल्य के संबंध में उपयोग कर सकता हूं।

df.rename(columns=lambda x, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

और जैसा कि मैंने सोपीथॉन चैट में लोगों द्वारा इंगित किया है, अगर मैं x और y बीच में * जोड़ता हूं, तो मैं अपने y चर को सुरक्षित रख सकता हूं। हालांकि, इस संदर्भ में मुझे विश्वास नहीं है कि इसे सुरक्षा की जरूरत है। यह अभी भी उल्लेखनीय लायक है।

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

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

pd.dateframe -> pymongo नोट: मैं इसे 5 से 10k रिकॉर्ड रखने के लिए chunksize में read_csv का उपयोग करता chunksize (pymongo बड़े होने पर सॉकेट को छोड़ देता है)

aCollection.insert((a[1].to_dict() for a in df.iterrows()))

पूछताछ: gt = से अधिक ...

pd.DataFrame(list(mongoCollection.find({'anAttribute':{'$gt':2887000, '$lt':2889000}})))

.find() एक पुनरावर्तक देता है, इसलिए मैं आमतौर पर छोटे iterators में काटने के लिए ichunked का उपयोग करें।

एक साथ जुड़ने के बारे में कैसे है क्योंकि मुझे आम तौर पर एक साथ पेस्ट करने के लिए 10 डेटा स्रोत मिलते हैं:

aJoinDF = pandas.DataFrame(list(mongoCollection.find({'anAttribute':{'$in':Att_Keys}})))

फिर (मेरे मामले में कभी-कभी मुझे अपने "विलय योग्य" से पहले एक aJoinDF पर aJoinDF पड़ता है।)

df = pandas.merge(df, aJoinDF, on=aKey, how='left')

और फिर आप नीचे दिए गए अद्यतन विधि के माध्यम से अपने मुख्य संग्रह में नई जानकारी लिख सकते हैं। (लॉजिकल संग्रह बनाम भौतिक डेटा स्रोत)।

collection.update({primarykey:foo},{key:change})

छोटे लुकअप पर, बस denormalize। उदाहरण के लिए, आपके पास दस्तावेज़ में कोड है और आप केवल फ़ील्ड कोड टेक्स्ट जोड़ते हैं और दस्तावेज़ बनाते समय एक dict लुकअप करते हैं।

अब आपके पास एक व्यक्ति के चारों ओर एक अच्छा डेटासेट है, आप प्रत्येक मामले पर अपने तर्क को मुक्त कर सकते हैं और अधिक विशेषताओं को बना सकते हैं। आखिरकार आप मेमोरी अधिकतम कुंजी संकेतकों के लिए अपने 3 पांडा में पढ़ सकते हैं और पिवॉट / एजीजी / डेटा एक्सप्लोरेशन कर सकते हैं। यह मेरे लिए 3 मिलियन रिकॉर्ड के लिए काम करता है जिसमें संख्या / बड़े पाठ / श्रेणियां / कोड / फ्लोट / ...

आप MongoDB (MapReduce और समग्र ढांचे) में निर्मित दो विधियों का भी उपयोग कर सकते हैं। समेकित ढांचे के बारे में अधिक जानकारी के लिए यहां देखें , क्योंकि यह मैपरेडस से आसान लगता है और त्वरित कुल काम के लिए आसान दिखता है। नोटिस मुझे अपने क्षेत्रों या रिश्तों को परिभाषित करने की आवश्यकता नहीं थी, और मैं दस्तावेज़ में आइटम जोड़ सकता हूं। तेजी से बदलते numpy, पांडा, पायथन टूलसेट की वर्तमान स्थिति में, MongoDB मुझे काम करने में मदद करता है :)





python pandas replace dataframe rename