একটি ডিকের সাহায্যে পান্ডাস কলামে মানগুলি পুনরায় সংগ্রহ করুন


317

আমার কাছে একটি অভিধান রয়েছে যা দেখতে এরকম দেখাচ্ছে: di = {1: "A", 2: "B"}

আমি এটির মতো ডেটাফ্রেমের "কল 1" কলামে এটি প্রয়োগ করতে চাই:

     col1   col2
0       w      a
1       1      2
2       2    NaN

পেতে:

     col1   col2
0       w      a
1       A      2
2       B    NaN

আমি কীভাবে সেরা এটি করতে পারি? কোনও কারণে এটি সম্পর্কিত গুগলিং শর্তাদি কেবল আমাকে কীভাবে ডিক্টস এবং এর বিপরীতে কলম তৈরি করতে পারে তার লিঙ্কগুলি দেখায়: - /

উত্তর:


339

আপনি ব্যবহার করতে পারেন .replace। উদাহরণ স্বরূপ:

>>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}})
>>> di = {1: "A", 2: "B"}
>>> df
  col1 col2
0    w    a
1    1    2
2    2  NaN
>>> df.replace({"col1": di})
  col1 col2
0    w    a
1    A    2
2    B  NaN

বা সরাসরি Series, অর্থাৎ df["col1"].replace(di, inplace=True)


1
যখন col```` is tuple. The error info is 'ndarray (dtype = অবজেক্ট)' এবং 'tuple'``` টাইপগুলি তুলনা করতে না পারি তখন আমার পক্ষে কাজ করে না
Zhao

18
দেখে মনে হচ্ছে এটা আর কাজ করে না সব সময়ে , যা প্রদত্ত বিস্ময়কর নয় উত্তর 4 বছর আগে থেকে। এই ক্রিয়াকলাপটি কীভাবে সাধারণ হয় তা প্রদত্ত এই প্রশ্নের একটি নতুন উত্তর দরকার ...
প্রেস্টনএইচ

2
@ প্রিস্টনএইচ এটি আমার পক্ষে নিখুঁতভাবে কাজ করে। চলমান:'3.6.1 |Anaconda custom (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]'
ড্যান

এটা আমার জন্য কাজ করে. তবে কীভাবে আমি সমস্ত কলামে মানগুলি প্রতিস্থাপন করতে চাই?
ফামারগার

2
দেখানো উত্তরগুলির জন্য আমার পক্ষে কাজ করা একমাত্র পদ্ধতি ছিল সিরিজে সরাসরি প্রতিস্থাপন করা। ধন্যবাদ!
ডিরিগো

241

map তুলনায় অনেক দ্রুত হতে পারে replace

যদি আপনার অভিধানে একাধিক কী থাকে তবে ব্যবহার mapকরা তার চেয়েও দ্রুত হতে পারে replace। এই পদ্ধতির দুটি সংস্করণ রয়েছে, আপনার অভিধানটি সমস্ত সম্ভাব্য মানকে বহিরাগতভাবে ম্যাপ করে কিনা তার উপরও নির্ভর করে (এবং আপনি অ-ম্যাচগুলি তাদের মান রাখতে চান বা নাএনএসে রূপান্তরিত করতে চান কিনা):

অবসন্ন ম্যাপিং

এই ক্ষেত্রে, ফর্মটি খুব সহজ:

df['col1'].map(di)       # note: if the dictionary does not exhaustively map all
                         # entries then non-matched entries are changed to NaNs

যদিও mapবেশিরভাগ ক্ষেত্রে এটির তর্ক হিসাবে কোনও ফাংশন লাগে তবে এটি বিকল্পভাবে একটি অভিধান বা সিরিজ নিতে পারে: পান্ডাস.সেসরিজ.ম্যাপের জন্য ডকুমেন্টেশন

অ-ক্লান্তিহীন ম্যাপিং

আপনার যদি একটি অব্যাহত ম্যাপিং থাকে এবং অ-মিলগুলির জন্য বিদ্যমান ভেরিয়েবলগুলি ধরে রাখতে চান তবে আপনি যুক্ত করতে পারেন fillna:

df['col1'].map(di).fillna(df['col1'])

এখানে @ জেপিপির জবাব হিসাবে: দক্ষতার সাথে অভিধানের মাধ্যমে একটি পান্ডাস সিরিজের মানগুলি প্রতিস্থাপন করুন

benchmarks

পান্ডাস সংস্করণ 0.23.1 সহ নিম্নলিখিত ডেটা ব্যবহার করে:

di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" }
df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) })

এবং এর সাথে পরীক্ষা %timeitকরে দেখা যাচ্ছে যে mapএটি প্রায় 10x এর চেয়ে দ্রুত replace

দ্রষ্টব্য যে আপনার স্পিডআপটি mapআপনার ডেটার সাথে পৃথক হবে। বৃহত্তম স্পিডআপটি বৃহত অভিধান এবং সম্পূর্ণ প্রতিস্থাপনের সাথে উপস্থিত হয়। আরও বিস্তৃত মানদণ্ড এবং আলোচনার জন্য @ জেপিপি উত্তর (উপরে লিঙ্কিত) দেখুন।


17
এই উত্তরের কোডের শেষ ব্লকটি অবশ্যই সবচেয়ে মার্জিত নয়, তবে এই উত্তরটি কিছু creditণের দাবিদার। এটি বৃহত অভিধানের জন্য দ্রুততরতার অর্ডার এবং আমার সমস্ত র‌্যাম ব্যবহার করে না। এটি একটি অভিধান ব্যবহার করে 10,000 টি লাইনের ফাইলটি পুনরায় তৈরি করেছে যার অর্ধ মিনিটের মধ্যে প্রায় 9 মিলিয়ন এন্ট্রি রয়েছে। df.replaceফাংশন, যখন পরিপাটি এবং ছোট dicts জন্য দরকারী, 20 মিনিট বা তাই জন্য চলমান পরে ক্র্যাশ করেছে।
গ্রিফিং

1
সম্পর্কিত:
অভিধানের

@ গ্রিগ্রিফিন মতামতের জন্য ধন্যবাদ এবং নোট করুন যে আমি এই উত্তরটি অতঃপর অ-বিস্তৃত কেস (@ জেপ্পিকে ধন্যবাদ) করার জন্য খুব সহজ পদ্ধতিতে আপডেট করেছি
জন

1
mapএমন একটি replace
সূচীতেও

1
@ অ্যালেক্সএসবি আমি সম্পূর্ণ সাধারণ উত্তর দিতে পারি না, তবে আমি মনে করি মানচিত্রটি আরও দ্রুত হবে এবং একই জিনিস সম্পাদন করবে (আমি মনে করি)। সাধারণত, একত্রে একই জিনিসটি করা অন্যান্য বিকল্পের তুলনায় ধীর হতে চলেছে।
জন

59

আপনার প্রশ্নে কিছুটা অস্পষ্টতা রয়েছে। কমপক্ষে তিনটি ব্যাখ্যা রয়েছে:

  1. diসূচক মানগুলিতে উল্লেখযোগ্য কীগুলি
  2. মানগুলি diউল্লেখ কীdf['col1']
  3. diসূচীর অবস্থানগুলিতে নির্দেশিত কীগুলি (ওপির প্রশ্ন নয়, তবে মজাদার জন্য নিক্ষেপ করা হয়েছে))

নীচে প্রতিটি ক্ষেত্রে একটি সমাধান দেওয়া হয়।


কেস 1: যদি কীগুলি diসূচক মানগুলিকে বোঝায় তবে আপনি updateপদ্ধতিটি ব্যবহার করতে পারেন :

df['col1'].update(pd.Series(di))

উদাহরণ স্বরূপ,

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1':['w', 10, 20],
                   'col2': ['a', 30, np.nan]},
                  index=[1,2,0])
#   col1 col2
# 1    w    a
# 2   10   30
# 0   20  NaN

di = {0: "A", 2: "B"}

# The value at the 0-index is mapped to 'A', the value at the 2-index is mapped to 'B'
df['col1'].update(pd.Series(di))
print(df)

উৎপাদনের

  col1 col2
1    w    a
2    B   30
0    A  NaN

আমি আপনার মূল পোস্ট থেকে মানগুলি সংশোধন করেছি তাই এটি কী updateকরছে তা স্পষ্ট । কীগুলি কীভাবে diসূচক মানগুলির সাথে সম্পর্কিত তা নোট করুন । সূচকের মানগুলির ক্রম - যা সূচকের অবস্থানগুলি - তাতে কিছু আসে যায় না।


কেস 2: মানগুলিতে যদি কীগুলি diউল্লেখ থাকে df['col1']তবে @ ড্যান অ্যালান এবং @ ডিএসএম এটি কীভাবে এটি অর্জন করবেন তা দেখায় replace:

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1':['w', 10, 20],
                   'col2': ['a', 30, np.nan]},
                  index=[1,2,0])
print(df)
#   col1 col2
# 1    w    a
# 2   10   30
# 0   20  NaN

di = {10: "A", 20: "B"}

# The values 10 and 20 are replaced by 'A' and 'B'
df['col1'].replace(di, inplace=True)
print(df)

উৎপাদনের

  col1 col2
1    w    a
2    A   30
0    B  NaN

নোট কিভাবে এই ক্ষেত্রে মধ্যে কী diখেলায় পরিবর্তন করা হয়েছে মান মধ্যে df['col1']


কেস 3: যদি diসূচিগুলির অবস্থানগুলি সম্পর্কিত কীগুলি থাকে তবে আপনি ব্যবহার করতে পারেন

df['col1'].put(di.keys(), di.values())

থেকে

df = pd.DataFrame({'col1':['w', 10, 20],
                   'col2': ['a', 30, np.nan]},
                  index=[1,2,0])
di = {0: "A", 2: "B"}

# The values at the 0 and 2 index locations are replaced by 'A' and 'B'
df['col1'].put(di.keys(), di.values())
print(df)

উৎপাদনের

  col1 col2
1    A    a
2   10   30
0    B  NaN

এখানে, প্রথম ও তৃতীয় সারি, রদবদল হয়েছে কারণ কী মধ্যে diহয় 0এবং 2যা পাইথন এর 0 ভিত্তিক ইন্ডেক্স সঙ্গে প্রথম ও তৃতীয় অবস্থানে পড়ুন।


replaceসমানভাবে ভাল, এবং এখানে যা ঘটছে তার জন্য আরও ভাল শব্দ।
ড্যান অ্যালান

অপের পোস্টের লক্ষ্যযুক্ত ডেটারফ্রেম কি অস্পষ্টতা দূর করে না? তবুও, এই উত্তরটি দরকারী, সুতরাং +1।
ডিএসএম

@ ডিএসএম: ওফস, আপনি ঠিক আছেন কেস 3 এর কোনও সম্ভাবনা নেই, তবে আমি মনে করি না যে ওপি'র টার্গেট ডেটাফ্রেম কেস 1 থেকে কেস 1 কে আলাদা করবে কারণ সূচক মানগুলি কলাম মানগুলির সাথে সমান হয়।
আনটবু

পোস্ট করা অন্য বেশিরভাগের মতো, @ ডিএসএমের পদ্ধতিটি দুর্ভাগ্যক্রমে আমার পক্ষে কার্যকর হয়নি, তবে @ আনতুবু'র কেস 1 কাজ করেছে। update()তুলনায় কিছুটা ক্লডজি মনে হয় replace()তবে কমপক্ষে এটি কাজ করে।
জিওফ

4

এই ডেটাফ্রেমে আপনার পুনর্নির্মাণের জন্য যদি কখনও একাধিক কলাম থাকে তবে এই প্রশ্নে যুক্ত করা:

def remap(data,dict_labels):
    """
    This function take in a dictionnary of labels : dict_labels 
    and replace the values (previously labelencode) into the string.

    ex: dict_labels = {{'col1':{1:'A',2:'B'}}

    """
    for field,values in dict_labels.items():
        print("I am remapping %s"%field)
        data.replace({field:values},inplace=True)
    print("DONE")

    return data

আশা করি এটি কারও কাজে লাগতে পারে।

চিয়ার্স


1
এই কার্যকারিতাটি ইতিমধ্যে সরবরাহ করা হয়েছে DataFrame.replace(), যদিও এটি কখন যুক্ত হয়েছিল তা আমি জানি না।
এএমসি

3

ডিএসএমের গ্রহণযোগ্য উত্তর রয়েছে তবে কোডিংটি সবার জন্য কাজ করে না বলে মনে হচ্ছে। পান্ডার বর্তমান সংস্করণ (8/2018 অনুসারে 0.23.4) এর সাথে এটি কাজ করে:

import pandas as pd

df = pd.DataFrame({'col1': [1, 2, 2, 3, 1],
            'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']})

conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1}
df['converted_column'] = df['col2'].replace(conversion_dict)

print(df.head())

আপনি দেখতে পাবেন এরকম দেখতে:

   col1      col2  converted_column
0     1  negative                -1
1     2  positive                 1
2     2   neutral                 0
3     3   neutral                 0
4     1  positive                 1

পান্ডাসের জন্য ডকস.ডাটা ফ্রেম.রেপ্লেস এখানে রয়েছে


আমি কখনই ডিএসএম এর উত্তর চালাতে সমস্যা পাইনি এবং আমি অনুমান করতে পারি যে উচ্চ ভোট মোট বেশিরভাগ লোকই দেয় নি। আপনার যে সমস্যাটি হচ্ছে তা সম্পর্কে আপনি আরও সুনির্দিষ্ট হতে চান। হতে পারে এটি আপনার নমুনা ডেটার সাথে সম্পর্কিত যা ডিএসএমের চেয়ে আলাদা?
জন

হুম, সম্ভবত একটি সংস্করণ সমস্যা। তবুও, উভয় উত্তর এখন এখানে।
শব্দসুবিহীন

1
গৃহীত উত্তরের সমাধানটি কেবলমাত্র নির্দিষ্ট ধরণের ক্ষেত্রে কাজ করে, Series.map()আরও নমনীয় বলে মনে হয়।
এএমসি

2

বা কর apply:

df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x))

ডেমো:

>>> df['col1']=df['col1'].apply(lambda x: {1: "A", 2: "B"}.get(x,x))
>>> df
  col1 col2
0    w    a
1    1    2
2    2  NaN
>>> 

যখন আপনার diডিক তালিকাগুলি হ'ল তখন কী হবে ? আপনি কিভাবে তালিকার এক মান মানচিত্র করতে পারেন?
ফ্যাকফি

আপনি পারেন, যদিও আমি দেখতে পাচ্ছি না আপনি কেন করবেন।
এএমসি

2

mapপ্রতিস্থাপনের চেয়ে দেওয়া (@ জন এর সমাধান) এর চেয়ে দ্রুততর দেওয়া হল যেখানে আপনাকে নির্দিষ্ট মানগুলি মানচিত্র করারNaN ইচ্ছায় নন-এক্সহসিয়েটিভ ম্যাপিংয়ের বিষয়ে আপনাকে সতর্ক হওয়া দরকার । এই ক্ষেত্রে যথাযথ পদ্ধতির জন্য আপনার maskযখন সিরিজ থাকে তখন .fillnaঅন্যথায় আপনি ম্যাপিংটি পূর্বাবস্থায় ফেরান NaN

import pandas as pd
import numpy as np

d = {'m': 'Male', 'f': 'Female', 'missing': np.NaN}
df = pd.DataFrame({'gender': ['m', 'f', 'missing', 'Male', 'U']})

keep_nan = [k for k,v in d.items() if pd.isnull(v)]
s = df['gender']

df['mapped'] = s.map(d).fillna(s.mask(s.isin(keep_nan)))

    gender  mapped
0        m    Male
1        f  Female
2  missing     NaN
3     Male    Male
4        U       U

1

একটি দুর্দান্ত সম্পূর্ণ সমাধান যা আপনার শ্রেণীর লেবেলের মানচিত্র রাখে:

labels = features['col1'].unique()
labels_dict = dict(zip(labels, range(len(labels))))
features = features.replace({"col1": labels_dict})

এইভাবে, আপনি যে কোনও সময়ে লেবেল_ডিক্ট থেকে মূল শ্রেণীর লেবেলটি উল্লেখ করতে পারেন।


1

নিকো কোলিয়ার (একাধিক কলামে প্রয়োগ করুন) এবং ইউ 10-ফরোয়ার্ড (পদ্ধতিগুলির প্রয়োগের স্টাইল ব্যবহার করে) যা প্রস্তাব করেছেন তার এক্সটেনশন হিসাবে এবং এটিকে সংক্ষিপ্তসার হিসাবে আমি প্রস্তাব করছি:

df.loc[:,['col1','col2']].transform(lambda x: x.map(lambda x: {1: "A", 2: "B"}.get(x,x))

.transform()একটি সিরিজের অংশ হিসাবে প্রতিটি কলামের প্রক্রিয়া করে। .apply()যার বিপরীতে একটি ডেটা ফ্রেমে একত্রিত কলামগুলি পাস করে।

ফলস্বরূপ আপনি সিরিজ পদ্ধতি প্রয়োগ করতে পারেন map()

অবশেষে, এবং আমি ইউ 10 এর জন্য ধন্যবাদ এই আচরণটি আবিষ্কার করেছিলাম, আপনি .get () এক্সপ্রেশনটিতে পুরো সিরিজটি ব্যবহার করতে পারেন। যদি না আমি এর আচরণ সম্পর্কে ভুল বুঝে থাকি এবং এটি ধারাবাহিকভাবে বিটওয়্যার পরিবর্তে সিরিজটি প্রসেস করে। মানের জন্য অ্যাকাউন্টগুলি আপনাকে আপনার ম্যাপিং অভিধান যার দ্বারা অন্যথায় ন্যান হিসেবে বিবেচনা করা করবে উল্লেখ না পদ্ধতি
.get(x,x).map()


.transform()একটি সিরিজের অংশ হিসাবে প্রতিটি কলামের প্রক্রিয়া করে। .apply()যার বিপরীতে একটি ডেটা ফ্রেমে একত্রিত কলামগুলি পাস করে। আমি চেষ্টা করেছি, apply()ঠিক আছে। locউভয়ই ব্যবহার করার দরকার নেই , এটি অত্যধিক জটিল বলে মনে হচ্ছে। df[["col1", "col2"]].apply(lambda col: col.map(lambda elem: my_dict.get(elem, elem)))ঠিক কাজ করা উচিত। অ্যাকাউন্ট মানের জন্য আপনি আপনার ম্যাপিং অভিধান যার দ্বারা অন্যথায় ন্যান হিসেবে বিবেচনা করা করবে উল্লেখ না পদ্ধতি এছাড়াও আপনি ব্যবহার করতে পারে পরে। .get(x,x).map()fillna()
এএমসি

অবশেষে, এবং আমি ইউ 10 এর জন্য ধন্যবাদ এই আচরণটি আবিষ্কার করেছিলাম, আপনি .get () এক্সপ্রেশনটিতে পুরো সিরিজটি ব্যবহার করতে পারেন। যদি না আমি এর আচরণ সম্পর্কে ভুল বুঝে থাকি এবং এটি ধারাবাহিকভাবে বিটওয়্যার পরিবর্তে সিরিজটি প্রসেস করে। আমি এটিকে পুনরুত্পাদন করতে পারি না, আপনি কি বিস্তারিত বলতে পারবেন? অভিন্ন নামযুক্ত ভেরিয়েবলগুলি এখানে সম্ভবত কিছু ভূমিকা পালন করছে।
এএমসি

0

নীচের মত আরও প্রতিস্থাপন ফাংশন প্রয়োগ করার জন্য আরও একটি নেটিভ পান্ডাস পদ্ধতির রয়েছে:

def multiple_replace(dict, text):
  # Create a regular expression  from the dictionary keys
  regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))

  # For each match, look-up corresponding value in dictionary
  return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text) 

একবার আপনি ফাংশনটি সংজ্ঞায়িত করার পরে, আপনি এটি আপনার ডেটাফ্রেমে প্রয়োগ করতে পারেন।

di = {1: "A", 2: "B"}
df['col1'] = df.apply(lambda row: multiple_replace(di, row['col1']), axis=1)

একটি আরও নেটিভ পান্ডা পদ্ধতির নীচে হিসাবে একটি প্রতিস্থাপন ফাংশন প্রয়োগ করা হয় পান্ডাদের দেওয়া সহজতর পদ্ধতির চেয়ে কীভাবে আরও "দেশীয়" (আইডোমেটিক?)?
এএমসি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.