পান্ডায় অন্য মানের উপর ভিত্তি করে একটি মান পরিবর্তন করুন


116

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

ধরা যাক আমি কলামের শিরোনামের আইডি'র সমস্ত মানগুলিতে পুনরাবৃত্তি করতে চাই। যদি সেই আইডি একটি নির্দিষ্ট সংখ্যার সাথে মেলে, তবে আমি দুটি অনুরূপ মান ফার্স্টনেম এবং লাস্টনাম পরিবর্তন করতে চাই।

স্টাটাতে এটি দেখতে এটির মতো দেখাচ্ছে:

replace FirstName = "Matt" if ID==103
replace LastName =  "Jones" if ID==103

সুতরাং এটি ফার্স্টনেমে সমস্ত মান প্রতিস্থাপন করে যা আইডি == 103 ম্যাট থেকে মানগুলির সাথে মিলে যায়।

পান্ডাসে, আমি এই জাতীয় কিছু চেষ্টা করছি

df = read_csv("test.csv")
for i in df['ID']:
    if i ==103:
          ...

এখান থেকে যেতে যেখানে নিশ্চিত নন। কোন ধারনা?

উত্তর:


195

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

ধরে নেওয়া যাক আপনি সরাসরি আপনার ডেটা লোড করতে পারেন pandasসঙ্গে pandas.read_csvতারপর নিচের কোডটি আপনার জন্য সহায়ক হতে পারে।

import pandas
df = pandas.read_csv("test.csv")
df.loc[df.ID == 103, 'FirstName'] = "Matt"
df.loc[df.ID == 103, 'LastName'] = "Jones"

মন্তব্যে উল্লিখিত হিসাবে, আপনি উভয় কলামে একটি শটে অ্যাসাইনমেন্টটিও করতে পারেন:

df.loc[df.ID == 103, ['FirstName', 'LastName']] = 'Matt', 'Jones'

নোট করুন যে ওভাররাইট অ্যাসাইনমেন্ট ক্রিয়াকলাপগুলির জন্য pandasআপনাকে ব্যবহার করতে 0.11 বা আরও নতুন সংস্করণ প্রয়োজন loc


এটি করার আরেকটি উপায় হ'ল যাকে চেইন অ্যাসাইনমেন্ট বলে use এর আচরণ কম স্থিতিশীল এবং তাই এটি সেরা সমাধান হিসাবে বিবেচিত হয় না (এটি ডক্সে স্পষ্টভাবে নিরুৎসাহিত করা হয়) তবে এটি সম্পর্কে জানার জন্য এটি দরকারী:

import pandas
df = pandas.read_csv("test.csv")
df['FirstName'][df.ID == 103] = "Matt"
df['LastName'][df.ID == 103] = "Jones"

16
এই df.loc[df.ID == 103, ['FirstName', 'LastName']] = 'Matt', 'Jones'
স্বাদটি

4
-1 "এটির আরেকটি উপায় হ'ল চেইন অ্যাসাইনমেন্ট বলা হয় যা ব্যবহার করা।" না জোর দিয়ে, না। এটি কেবল এটি জেনে রাখা কার্যকর যে শিকলযুক্ত কার্যভার নির্ভরযোগ্য নয়। এটি এমন নয় যে এটি একটি নির্ভরযোগ্য, অপ-অনুকূল সমাধান নয়, পরিস্থিতি আরও খারাপ । এমনকি আপনি স্ট্যাক ওভারফ্লোতে অন্য কোথাও এটি স্বীকার করেছেন । শৃঙ্খলিত কার্যনির্বাহী একটি কার্যকর বিকল্প হিসাবে এই ভ্রমটি এড়াতে চেষ্টা করুন। আপনি যে প্রথম দুটি পদ্ধতি দিয়েছেন তা যথেষ্ট ছিল এবং এটি করার পছন্দীয় উপায়।
ফিলিপ ক্লাউড

9
আমি একমত নই আমি বুঝতে পারি না যে আপনি কেন প্যাডেন্টিকভাবে দৃ as়তা অবলম্বন করে বলছেন যে শৃঙ্খলিত কার্যভারটি কার্যকর উপায় নয়। আমি স্বীকার করেছি যে এটি পছন্দসই উপায় হিসাবে বিবেচিত হয় না। আপনি আরো কি করতে চান. এটা তোলে কাজ করতে মত এই নয় ভ্রান্ত এর একটি এটা করতে উপায়। আসলে, আমার সিস্টেমে এখনই (সংস্করণ 0.8), এটি করার সঠিক উপায় । আপনি যদি এই অবস্থানটি গ্রহণ করতে যান তবে আমি আপনার আপ-ভোটে আগ্রহী নই। আপনার পয়েন্টটি ডাউনটোটের সাথে সংকেত নির্দ্বিধায় বোধ করুন তবে আমি ইতিমধ্যে আপনার বক্তব্যটির প্রতিফলন করেছি এবং এর সাথে একমত নই।
ইলি

11
ইন্টারনেট গুরুতর ব্যবসা। যে কোনও হারে, ইএমএস, বিকল্পটি উপস্থিত রয়েছে তা জেনে আমি প্রশংসা করি।
পার্সেলটাঙ্গয়ে

আপনি যে সমস্যার সমাধান করতে পারেন তা হ'ল সিএসভির কলামের নাম এবং অ্যাসাইনমেন্টগুলিতে পিরিয়ড / ডট রয়েছে। আপনি এই জাতীয় কিছু ব্যবহার করে কলামগুলি ঠিক করতে পারেন: কলস = df.colলাম কলস = কলস.ম্যাপ (ল্যাম্বডা এক্স: এক্স.রেপ্লেস ('।', '_') যদি আইসনস্ট্যান্স (এক্স, স্ট্রিং) অন্য এক্স) ডিএফ কোডস = COLS
ski_squaw

39

আপনি ব্যবহার করতে পারেন map, এটি কোনও স্বৈরশাসক বা এমনকি কোনও কাস্টম ফাংশন থেকে ভেলস মানচিত্র করতে পারে।

মনে করুন এটি আপনার ডিএফ:

    ID First_Name Last_Name
0  103          a         b
1  104          c         d

ডিক্টস তৈরি করুন:

fnames = {103: "Matt", 104: "Mr"}
lnames = {103: "Jones", 104: "X"}

এবং মানচিত্র:

df['First_Name'] = df['ID'].map(fnames)
df['Last_Name'] = df['ID'].map(lnames)

ফলাফলটি হবে:

    ID First_Name Last_Name
0  103       Matt     Jones
1  104         Mr         X

অথবা একটি কাস্টম ফাংশন ব্যবহার করুন:

names = {103: ("Matt", "Jones"), 104: ("Mr", "X")}
df['First_Name'] = df['ID'].map(lambda x: names[x][0])

4
মানগুলি যদি আপনার ডিকটিতে উপস্থিত না থাকে তবে এটি কী কীররার তৈরি করবে না?
এডচুম

4
কাস্টম ফাংশনটি করবে, অন্যরা যেভাবেই কাজ করবে। তবে আমি ধরে dictনিয়েছি ম্যাপিংয়ের জন্য তৈরি করা হয়েছে। অন্যথায় কিছু চেকিং / পরিষ্কারের মতো কিছু করা যেতে পারে:df.ID.isin(names.keys())
রাটার ক্যাসিস

কাস্টম ফাংশনটি কোনও (অজ্ঞাতনামা) ফাংশনে প্রসারিত হতে পারে।
ব্যবহারকারী 989762

16

মূল প্রশ্নটি একটি নির্দিষ্ট সংকীর্ণ ব্যবহারের ক্ষেত্রে সম্বোধন করে। যাদের আরও জেনেরিক উত্তর প্রয়োজন তাদের জন্য এখানে কয়েকটি উদাহরণ রয়েছে:

অন্যান্য কলামগুলি থেকে ডেটা ব্যবহার করে একটি নতুন কলাম তৈরি করা হচ্ছে

নীচে ডেটাফ্রেম দেওয়া হয়েছে:

import pandas as pd
import numpy as np

df = pd.DataFrame([['dog', 'hound', 5],
                   ['cat', 'ragdoll', 1]],
                  columns=['animal', 'type', 'age'])

In[1]:
Out[1]:
  animal     type  age
----------------------
0    dog    hound    5
1    cat  ragdoll    1

নীচে আমরা ক্রিয়াকলাপটি সিরিজের জন্য ওভাররাইড করা descriptionব্যবহার করে অন্যান্য কলামগুলির সংলগ্ন হিসাবে একটি নতুন কলাম যুক্ত করছি +। অভিনব স্ট্রিং ফর্ম্যাটিং, এফ-স্ট্রিংস ইত্যাদি এখানে কাজ করবে না যেহেতু +স্কেলারের ক্ষেত্রে প্রযোজ্য এবং 'আদিম' মানগুলি নয়:

df['description'] = 'A ' + df.age.astype(str) + ' years old ' \
                    + df.type + ' ' + df.animal

In [2]: df
Out[2]:
  animal     type  age                description
-------------------------------------------------
0    dog    hound    5    A 5 years old hound dog
1    cat  ragdoll    1  A 1 years old ragdoll cat

আমরা 1 yearsবিড়ালের জন্য 1 yearপেয়েছি (পরিবর্তে ) যা আমরা নীচে শর্তযুক্ত ব্যবহার করে ঠিক করব।

শর্তসাপেক্ষে একটি বিদ্যমান কলাম পরিবর্তন করে

এখানে আমরা animalঅন্যান্য কলামের মানগুলির সাথে মূল কলামটি প্রতিস্থাপন করছি এবং np.whereএর মানের উপর ভিত্তি করে একটি শর্তাধীন সাবস্ট্রিং সেট করতে ব্যবহার করছি age:

# append 's' to 'age' if it's greater than 1
df.animal = df.animal + ", " + df.type + ", " + \
    df.age.astype(str) + " year" + np.where(df.age > 1, 's', '')

In [3]: df
Out[3]:
                 animal     type  age
-------------------------------------
0   dog, hound, 5 years    hound    5
1  cat, ragdoll, 1 year  ragdoll    1

শর্তসাপেক্ষে একাধিক কলাম পরিবর্তন করা

একটি আরও .apply()কমনীয় পদ্ধতির একটি একক কলামের চেয়ে পুরো ডেটাফ্রেমে কল করা:

def transform_row(r):
    r.animal = 'wild ' + r.type
    r.type = r.animal + ' creature'
    r.age = "{} year{}".format(r.age, r.age > 1 and 's' or '')
    return r

df.apply(transform_row, axis=1)

In[4]:
Out[4]:
         animal            type      age
----------------------------------------
0    wild hound    dog creature  5 years
1  wild ragdoll    cat creature   1 year

উপরের কোডে transform_row(r)ফাংশন Seriesএকটি প্রদত্ত সারির প্রতিনিধিত্ব করে এমন একটি বস্তু গ্রহণ করে ( axis=1এটি দ্বারা নির্দেশিত , এর ডিফল্ট মান প্রতিটি কলামের জন্য axis=0একটি Seriesবস্তু সরবরাহ করবে )। এটি প্রক্রিয়াটিকে সহজতর করে যেহেতু আমরা কলামের নামগুলি ব্যবহার করে সারিতে প্রকৃত 'আদিম' মানগুলি অ্যাক্সেস করতে পারি এবং প্রদত্ত সারি / কলামে অন্যান্য কক্ষগুলির দৃশ্যমানতা অর্জন করতে পারি।


4
এরকম একটি বিস্তৃত উত্তর লেখার জন্য সময় দেওয়ার জন্য ধন্যবাদ। অনেক প্রশংসিত.
পার্সেলটাংয়ে

এই অত্যন্ত সহায়ক উত্তরের জন্য ধন্যবাদ। একটি ফলোআপ - যদি আমরা কলামটিতে স্ট্রিং সংশোধন না করে গণিত করে একটি কলাম পরিবর্তন করতে চাই? উদাহরণস্বরূপ, উপরের উদাহরণটি ব্যবহার করে, আমরা যদি df.animal == 'কুকুর' থেকে df.age কলামটি 7 দ্বারা গুণন করতে চাই? ধন্যবাদ!
জিবিজি

4
@ জিবিজি: np.whereসম্ভবত আপনি যা খুঁজছেন তা হ'ল, উদাহরণস্বরূপ stackoverflow.com/a/42540310/191246 দেখুন তবে এটিও সম্ভব যে আপনি যুক্তিটিকে একটি স্কেলার অপারেশনে ফিট করতে পারবেন না, তবে আপনাকে স্পষ্টভাবে রূপান্তর করতে হবে এটি কীভাবে করা হয়েছে transform_row
সেটির

আপনাকে ধন্যবাদ @ সিপিপিজ্জা! শুধু আমি যা খুঁজছিলাম।
জিবিজি

13

এই প্রশ্নটি এখনও প্রায়শই পরিদর্শন করা যেতে পারে যে মিঃ ক্যাসিজের উত্তরে একটি সংশোধন প্রস্তাব দেওয়া উচিত। dictবিল্ট-ইন বর্গ উপ-দলেই যাতে একটি ডিফল্ট নিখোঁজ কী জন্য ফিরিয়ে দেওয়া হয় হতে পারে। এই প্রক্রিয়াটি পান্ডাদের জন্য ভাল কাজ করে। তবে নীচে দেখুন।

এইভাবে কী ত্রুটিগুলি এড়ানো সম্ভব।

>>> import pandas as pd
>>> data = { 'ID': [ 101, 201, 301, 401 ] }
>>> df = pd.DataFrame(data)
>>> class SurnameMap(dict):
...     def __missing__(self, key):
...         return ''
...     
>>> surnamemap = SurnameMap()
>>> surnamemap[101] = 'Mohanty'
>>> surnamemap[301] = 'Drake'
>>> df['Surname'] = df['ID'].apply(lambda x: surnamemap[x])
>>> df
    ID  Surname
0  101  Mohanty
1  201         
2  301    Drake
3  401         

একই জিনিস নিম্নলিখিত পদ্ধতিতে আরও সহজভাবে করা যেতে পারে। getডিক অবজেক্টের পদ্ধতির জন্য 'ডিফল্ট' আর্গুমেন্টের ব্যবহার ডিককে সাবক্লাস করা অপ্রয়োজনীয় করে তোলে।

>>> import pandas as pd
>>> data = { 'ID': [ 101, 201, 301, 401 ] }
>>> df = pd.DataFrame(data)
>>> surnamemap = {}
>>> surnamemap[101] = 'Mohanty'
>>> surnamemap[301] = 'Drake'
>>> df['Surname'] = df['ID'].apply(lambda x: surnamemap.get(x, ''))
>>> df
    ID  Surname
0  101  Mohanty
1  201         
2  301    Drake
3  401         

4
এটি এখন পর্যন্ত সেরা এবং সহজ উত্তর যা আমি দেখেছি, দুর্দান্ত ডিফল্ট হ্যান্ডলিং সহ। ধন্যবাদ.
ব্রেন্ডন

@ ব্রেন্ডন: ওহ! অনেক ধন্যবাদ.
বিল বেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.