একটি কলামে স্ট্রিংগুলি থেকে অযাচিত অংশগুলি সরান


129

আমি ডেটা ফ্রেম কলামের স্ট্রিংগুলি থেকে অযাচিত অংশগুলি অপসারণের কার্যকর উপায়টি খুঁজছি।

ডেটা দেখে মনে হচ্ছে:

    time    result
1    09:00   +52A
2    10:00   +62B
3    11:00   +44a
4    12:00   +30b
5    13:00   -110a

আমার এই ডেটাগুলি ট্রিম করতে হবে:

    time    result
1    09:00   52
2    10:00   62
3    11:00   44
4    12:00   30
5    13:00   110

আমি চেষ্টা করেছি .str.lstrip('+-')এবং। str.rstrip('aAbBcC'), কিন্তু একটি ত্রুটি পেয়েছে:

TypeError: wrapper() takes exactly 1 argument (2 given)

যে কোনও পয়েন্টার প্রশংসিত হবে!

উত্তর:


167
data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))

ধন্যবাদ! ওই কাজগুলো. আমি এখনও মানচিত্রের চারপাশে আমার মন জড়িয়ে রাখছি (), কখন এটি ব্যবহার করবেন বা ব্যবহার করবেন তা নিশ্চিত নই ...
ইয়ানান ওয়াং

আমি এই পদ্ধতিটি প্রতিস্থাপন ফাংশনটির সাথেও কাজ করে দেখে সন্তুষ্ট হয়েছিল।
বিকে

@ নিউমিরো প্রতিটি কলাম পুনরাবৃত্তি করলে আপনি এই ফলাফলটি কীভাবে প্রয়োগ করবেন?
medev21

আমি 12 নম্বর হিসাবে একটি নম্বর প্রতিস্থাপন করতে এই ফাংশনটি ব্যবহার করতে পারি? যদি আমি x.lstrip ('12 ') করি তবে এটি সমস্ত 1 এবং 2 গুলি কেটে যায়।
ডেভ

76

আমি কীভাবে একটি কলামের স্ট্রিংগুলি থেকে অযাচিত অংশগুলি সরিয়ে দেব?

মূল প্রশ্নটি পোস্ট করার years বছর পরে, পান্ডাসের এখন বেশ কয়েকটি "ভেক্টরাইজড" স্ট্রিং ফাংশন রয়েছে যা পারস্পরিকভাবে এই স্ট্রিং ম্যানিপুলেশন অপারেশনগুলি সম্পাদন করতে পারে।

এই উত্তরটি এই স্ট্রিংয়ের কয়েকটি ফাংশন অন্বেষণ করবে, দ্রুত বিকল্প প্রস্তাব করবে এবং শেষের দিকে একটি সময়ের তুলনায় চলে যাবে।


.str.replace

ম্যাচ করার জন্য স্ট্রিং / প্যাটার্ন এবং এর সাথে প্রতিস্থাপনের জন্য স্ট্রিংগুলি নির্দিষ্ট করুন।

pd.__version__
# '0.24.1'

df    
    time result
1  09:00   +52A
2  10:00   +62B
3  11:00   +44a
4  12:00   +30b
5  13:00  -110a

df['result'] = df['result'].str.replace(r'\D', '')
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

আপনার যদি ফলাফলটির পূর্ণসংখ্যায় রূপান্তর করতে হয় তবে আপনি ব্যবহার করতে পারেন Series.astype,

df['result'] = df['result'].str.replace(r'\D', '').astype(int)

df.dtypes
time      object
result     int64
dtype: object

আপনি যদি dfজায়গায় স্থান পরিবর্তন করতে না চান তবে ব্যবহার করুন DataFrame.assign:

df2 = df.assign(result=df['result'].str.replace(r'\D', ''))
df
# Unchanged

.str.extract

আপনি রাখতে চান সাবস্ট্রিংগুলি বের করার জন্য দরকারী Use

df['result'] = df['result'].str.extract(r'(\d+)', expand=False)
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

এর সাথে extract, কমপক্ষে একটি ক্যাপচার গ্রুপ নির্দিষ্ট করা প্রয়োজন। expand=Falseপ্রথম ক্যাপচার গ্রুপ থেকে ধরা পড়া আইটেমগুলির সাথে একটি সিরিজ ফেরত দেবে।


.str.split এবং .str.get

আপনার সমস্ত স্ট্রিং এই ধারাবাহিক কাঠামো অনুসরণ করে ধরে নিয়ে কাজ করে বিভাজন কাজ করে।

# df['result'] = df['result'].str.split(r'\D').str[1]
df['result'] = df['result'].str.split(r'\D').str.get(1)
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

আপনি যদি কোনও সাধারণ সমাধান খুঁজছেন তবে সুপারিশ করবেন না।


আপনি যদি str উপরের সংযোগ এবং পঠনযোগ্য অ্যাক্সেসর ভিত্তিক সমাধানগুলি দ্বারা সন্তুষ্ট হন তবে আপনি এখানে থামতে পারেন। তবে আপনি যদি দ্রুত, আরও পারফরম্যান্স বিকল্পে আগ্রহী হন তবে পড়তে থাকুন।


অনুকূলকরণ: তালিকা বিবেচনা

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

আমার লেখার জন্য , পান্ডাসে কি লুপগুলি সত্যই খারাপ? আমার কখন যত্ন করা উচিত? , আরও বিশদে যায়।

str.replaceবিকল্প ব্যবহার করে পুনরায় লেখা যেতে পারেre.sub

import re

# Pre-compile your regex pattern for more performance.
p = re.compile(r'\D')
df['result'] = [p.sub('', x) for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

str.extractউদাহরণ একটি তালিকা ধী ব্যবহার পুনরায় লেখা যেতে পারে re.search,

p = re.compile(r'\d+')
df['result'] = [p.search(x)[0] for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

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

def try_extract(pattern, string):
    try:
        m = pattern.search(string)
        return m.group(0)
    except (TypeError, ValueError, AttributeError):
        return np.nan

p = re.compile(r'\d+')
df['result'] = [try_extract(p, x) for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

আমরা তালিকা বোধগম্যতা ব্যবহার করে @ ইউমিরো এবং @ মনিবাটারের উত্তরগুলি আবারও লিখতে পারি:

df['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in df['result']]

এবং,

df['result'] = [x[1:-1] for x in df['result']]

NaN ইত্যাদি পরিচালনা করার জন্য একই বিধি প্রযোজ্য।


পারফরম্যান্স তুলনা

এখানে চিত্র বর্ণনা লিখুন

পারফ্লোট ব্যবহার করে উত্পন্ন গ্রাফ । আপনার রেফারেন্সের জন্য সম্পূর্ণ কোড তালিকা। সম্পর্কিত ফাংশন নীচে তালিকাভুক্ত করা হয়।

এগুলির মধ্যে কয়েকটি তুলনা অন্যায্য কারণ তারা ওপির ডেটা কাঠামোর সুবিধা নিয়ে থাকে তবে আপনি যা চান তা থেকে এটি নিয়ে যান। একটি বিষয় লক্ষণীয় যে প্রতিটি তালিকা বোঝার ফাংশন তার সমতুল্য পান্ডাস বৈকল্পিকের চেয়ে দ্রুত বা তুলনীয়।

ক্রিয়াকলাপ

def eumiro(df):
    return df.assign(
        result=df['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC')))

def coder375(df):
    return df.assign(
        result=df['result'].replace(r'\D', r'', regex=True))

def monkeybutter(df):
    return df.assign(result=df['result'].map(lambda x: x[1:-1]))

def wes(df):
    return df.assign(result=df['result'].str.lstrip('+-').str.rstrip('aAbBcC'))

def cs1(df):
    return df.assign(result=df['result'].str.replace(r'\D', ''))

def cs2_ted(df):
    # `str.extract` based solution, similar to @Ted Petrou's. so timing together.
    return df.assign(result=df['result'].str.extract(r'(\d+)', expand=False))

def cs1_listcomp(df):
    return df.assign(result=[p1.sub('', x) for x in df['result']])

def cs2_listcomp(df):
    return df.assign(result=[p2.search(x)[0] for x in df['result']])

def cs_eumiro_listcomp(df):
    return df.assign(
        result=[x.lstrip('+-').rstrip('aAbBcC') for x in df['result']])

def cs_mb_listcomp(df):
    return df.assign(result=[x[1:-1] for x in df['result']])

সেটিংউইথকপিওয়্যারিং এড়ানোর জন্য কোনও কর্মসূচী:Try using .loc[row_indexer,col_indexer] = value instead
পিভি 8

@ PV8 নিশ্চিত আপনার কোড সম্পর্কে না, কিন্তু এই চেক আউট: stackoverflow.com/questions/20625582/...
cs95

কেউ আমার মত Regex নতুন যে জন্য, \ ডি যেমন [^ \ ঘ] (কিছু যে একটি অঙ্ক নয়) একই এখান থেকে । সুতরাং আমরা মূলত স্ট্রিংয়ের সমস্ত অ-অঙ্কগুলি কিছু না দিয়ে প্রতিস্থাপন করছি।
ষি লাচমিয়ারস্যাড

56

আমি পান্ডাগুলি প্রতিস্থাপন ফাংশনটি ব্যবহার করব, আপনি খুব সহজ এবং শক্তিশালী হিসাবে আপনি রেজেক্স ব্যবহার করতে পারেন। নীচে আমি কোনও অ-অঙ্কের অক্ষর মুছে ফেলার জন্য রেজেক্স \ ডি ব্যবহার করছি তবে স্পষ্টতই আপনি রেজেক্সের সাথে বেশ সৃজনশীল হতে পারেন।

data['result'].replace(regex=True,inplace=True,to_replace=r'\D',value=r'')

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

@bgenchel - আমি এই পদ্ধতি ব্যবহৃত একটি pd.Series একটি স্ট্রিংয়ের অংশকে প্রতিস্থাপন: df.loc[:, 'column_a'].replace(regex=True, to_replace="my_prefix", value="new_prefix")। এটি "my_prefixaaa" এর মতো একটি স্ট্রিংকে "new_prefixaaa" তে রূপান্তর করবে।
জাকুব

r_ to torere = r '\ D' এ কী করবে?
লুকা গুয়ারো

পাইথন ডক্স থেকে @ লুকাগুয়ারো: "আর প্রিফিক্সটি, আক্ষরিককে কাঁচা স্ট্রিংকে আক্ষরিক বানিয়ে তোলা দরকার, কারণ নিয়মিত অভিব্যক্তির বিপরীতে পাইথনের দ্বারা স্বীকৃত নয় এমন একটি" "রান্না করা" স্ট্রিং আক্ষরিকের মধ্যে পালানোর অনুক্রমগুলি এখন প্রয়োজন now একটি অবমূল্যায়ন ওয়ার্নিংয়ের ফলস্বরূপ এবং অবশেষে সিন্ট্যাক্সেরর হয়ে যাবে ""
কোডার 375

35

নির্দিষ্ট ক্ষেত্রে যেখানে আপনি ডেটাফ্রেম কলাম থেকে যে অবস্থানগুলি সরাতে চান সেগুলি জানেন, আপনি সেই অংশগুলি থেকে মুক্তি পেতে ল্যাম্বডা ফাংশনের অভ্যন্তরে স্ট্রিং ইনডেক্সিং ব্যবহার করতে পারেন:

শেষ চরিত্র:

data['result'] = data['result'].map(lambda x: str(x)[:-1])

প্রথম দুটি অক্ষর:

data['result'] = data['result'].map(lambda x: str(x)[2:])

আমাকে জিও স্থানাঙ্কগুলি 8 টি অক্ষরে ট্রিম করতে হবে (সহ (।), (-)) এবং যদি সেগুলি 8 এর চেয়ে কম হয় তবে সমস্ত স্থানাঙ্ক 8 টি অক্ষর তৈরি করতে আমাকে শেষ পর্যন্ত '0' সন্নিবেশ করা দরকার। এটি করার সহজ উপায় কী?
সিটজ ব্লগজ

আমি আপনার সমস্যাটি পুরোপুরি বুঝতে পারছি না তবে আপনাকে ল্যাম্বডা ফাংশনটি "{0: .8f}" এর মতো কিছুতে পরিবর্তন করতে হবে format ফর্ম্যাট (x)
prl900

উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। সরল কথায় আমার কাছে জিও স্থানাঙ্কের সাথে ডেটাফ্রেম রয়েছে - অক্ষাংশ এবং দ্রাঘিমাংশ দুটি কলাম হিসাবে। অক্ষরের দৈর্ঘ্য 8 টিরও বেশি অক্ষর এবং আমি প্রথম থেকে শুরু করে কেবল 8 টি অক্ষর রেখেছিলাম যার মধ্যে (-) এবং (।) অন্তর্ভুক্ত হওয়া উচিত।
সিটজ ব্লগজ

18

সেখানে একটি বাগ এখানে: বর্তমানে আর্গুমেন্ট প্রেরণ করতে পারবেন না str.lstripএবং str.rstrip:

http://github.com/pydata/pandas/issues/2411

সম্পাদনা: 2012-12-07 এটি এখন দেব শাখায় কাজ করে:

In [8]: df['result'].str.lstrip('+-').str.rstrip('aAbBcC')
Out[8]: 
1     52
2     62
3     44
4     30
5    110
Name: result

11

একটি খুব সহজ পদ্ধতি extractহ'ল সমস্ত অঙ্ক নির্বাচন করার জন্য পদ্ধতিটি ব্যবহার করা । কেবল এটি নিয়মিত এক্সপ্রেশন সরবরাহ করুন '\d+'যা কোনও সংখ্যা ছাড়ায় ext

df['result'] = df.result.str.extract(r'(\d+)', expand=True).astype(int)
df

    time  result
1  09:00      52
2  10:00      62
3  11:00      44
4  12:00      30
5  13:00     110

7

আমি প্রায়শই এই ধরণের কাজের জন্য তালিকা বোধগম্যতা ব্যবহার করি কারণ তারা প্রায়শই দ্রুত হয়।

এই জাতীয় জিনিসগুলি করার জন্য বিভিন্ন পদ্ধতির মধ্যে পারফরম্যান্সে বড় পার্থক্য থাকতে পারে (অর্থাত্ একটি ডেটা ফ্রেমের মধ্যে একটি সিরিজের প্রতিটি উপাদানকে পরিবর্তন করা)। প্রায়শই একটি তালিকা বোঝার দ্রুততম হতে পারে - এই কাজের জন্য নীচে কোড দৌড় দেখুন:

import pandas as pd
#Map
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))
10000 loops, best of 3: 187 µs per loop
#List comprehension
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in data['result']]
10000 loops, best of 3: 117 µs per loop
#.str
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].str.lstrip('+-').str.rstrip('aAbBcC')
1000 loops, best of 3: 336 µs per loop

4

মনে করুন আপনার ডিএফ-তে সংখ্যার মধ্যেও সেই অতিরিক্ত চরিত্র রয়েছে last শেষ এন্ট্রি।

  result   time
0   +52A  09:00
1   +62B  10:00
2   +44a  11:00
3   +30b  12:00
4  -110a  13:00
5   3+b0  14:00

আপনি কেবল শুরু এবং শেষ থেকে নয় কিন্তু এর মধ্যে থেকেও অক্ষরগুলি সরাতে str.replace চেষ্টা করতে পারেন।

DF['result'] = DF['result'].str.replace('\+|a|b|\-|A|B', '')

আউটপুট:

  result   time
0     52  09:00
1     62  10:00
2     44  11:00
3     30  12:00
4    110  13:00
5     30  14:00

0

নিয়মিত অভিব্যক্তি ব্যবহার করে এটি ব্যবহার করে দেখুন:

import re
data['result'] = data['result'].map(lambda x: re.sub('[-+A-Za-z]',x)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.