2017-12-14 141 views
8

sử dụng Pandas để loại bỏ tất cả ngoại trừ giai đoạn cuối cùng trong một chuỗi như vậy:Thay thế tất cả nhưng sự xuất hiện cuối cùng của một nhân vật trong một dataframe

s = pd.Series(['1.234.5','123.5','2.345.6','678.9']) 
counts = s.str.count('\.') 
target = counts==2 
target 
0  True 
1 False 
2  True 
3 False 
dtype: bool 

s = s[target].str.replace('\.','',1) 
s 
0 1234.5 
2 2345.6 
dtype: object 

đầu ra mong muốn của tôi, tuy nhiên, là:

0 1234.5 
1 123.5 
2 2345.6 
3 678.9 
dtype: object 

Lệnh thay thế cùng với mục tiêu mặt nạ dường như đang giảm các giá trị không được thay thế và tôi không thể xem cách khắc phục điều này.

Trả lời

7

Tùy chọn 1
Mẫu regex này có str.replace nên làm tốt.

s.str.replace(r'\.(?=.*?\.)', '') 

0 1234.5 
1  123.5 
2 2345.6 
3  678.9 
dtype: object 

Ý tưởng là, miễn là có nhiều ký tự thay thế, hãy tiếp tục thay thế. Dưới đây là một phân tích về các biểu hiện thường xuyên sử dụng -

\.  # '.' 
(?= # positive lookahead 
.*? # match anything 
\.  # look for '.' 
) 

Lựa chọn 2
Nếu bạn muốn làm điều này bằng count, nó không phải là bất khả thi, nhưng nó là một thách thức. Bạn có thể làm điều này dễ dàng hơn với np.vectorize. Đầu tiên, xác định một chức năng -

def foo(r, c): 
    return r.replace('.', '', c) 

Vectorize nó -

v = np.vectorize(foo) 

Bây giờ, gọi hàm v, đi qua s và đếm để thay thế -

pd.Series(v(s, s.str.count(r'\.') - 1)) 

0 1234.5 
1  123.5 
2 2345.6 
3  678.9 
dtype: object 

Hãy ghi nhớ rằng đây về cơ bản là một vòng lặp được tôn vinh. Python tương đương với điều này sẽ là một cái gì đó giống như -

r = [] 
for x, y in zip(s, s.str.count(r'\.') - 1): 
    r.append(x.replace('.', '', y)) 

pd.Series(r) 

0 1234.5 
1  123.5 
2 2345.6 
3  678.9 
dtype: object 

Hoặc, sử dụng một danh sách hiểu -

pd.Series([x.replace('.', '', y) for x, y in zip(s, s.str.count(r'\.') - 1)]) 

0 1234.5 
1  123.5 
2 2345.6 
3  678.9 
dtype: object 
+0

Vì vậy, điều này thay thế bất kỳ khoảng thời gian nào miễn là một khoảng thời gian khác khớp với trước đó? Tôi có thể chấp nhận trong 3 phút haha, quá nhanh của bạn. – seanysull

+0

Là một sang một bên nó có thể được thực hiện theo cách tôi đã cố gắng? – seanysull

+0

@seanysull Hmm, với 'replace' và regex? Hmm, dù thế nào đi chăng nữa, bạn cần phải biết liệu có một nhân vật ở phía trước hay không, vì vậy không thể tránh được cái nhìn. –

0

Bạn muốn thay thế các mặt hàng đeo mặt nạ và giữ nguyên vẹn còn lại. Thats chính xác những gì Series.where hiện, ngoại trừ nó thay thế các giá trị unmasked, do đó bạn cần phải phủ nhận mặt nạ.

s.where(~target, s.str.replace('\.','',1)) 

Hoặc bạn có thể thực hiện thay đổi tại chỗ bằng cách gán giá trị đeo mặt nạ, điều này có lẽ rẻ hơn nhưng phá hoại.

s[target] = s[target].str.replace('\.','',1) 
Các vấn đề liên quan