Tạo một cột mới dựa trên điều kiện if-elif-else


100

Tôi có DataFrame df:

    A    B
a   2    2 
b   3    1
c   1    3

Tôi muốn tạo một cột mới dựa trên các tiêu chí sau:

nếu hàng A == B: 0

nếu hàngA > B: 1

nếu hàng A < B: -1

vì vậy với bảng trên, nó phải là:

    A    B    C
a   2    2    0
b   3    1    1
c   1    3   -1 

Đối với những if elsetrường hợp điển hình mà tôi làm np.where(df.A > df.B, 1, -1), liệu gấu trúc có cung cấp một cú pháp đặc biệt để giải quyết vấn đề của tôi với một bước (mà không cần tạo 3 cột mới rồi kết hợp kết quả) không?


Bạn chỉ có thể xác định một hàm và chuyển nó vào applyvà thiết lập axis=1sẽ hoạt động, không chắc tôi có thể nghĩ ra một phép toán sẽ cung cấp cho bạn những gì bạn muốn
EdChum

Giải pháp của bạn ngụ ý tạo 3 cột và kết hợp chúng thành 1 cột hoặc bạn có ý nghĩ gì khác?
nuthip

Bạn tiếp tục nói "tạo 3 cột", nhưng tôi không chắc bạn đang đề cập đến điều gì.
DSM

1
@DSM đã trả lời câu hỏi này nhưng ý tôi là đại loại như df['C']=df.apply(myFunc(row), axis=1)nơi myFunc làm những gì bạn muốn, điều này không liên quan đến việc tạo '3 cột'
EdChum

Câu trả lời:


146

Để chính thức hóa một số cách tiếp cận đã nêu ở trên:

Tạo một hàm hoạt động trên các hàng của khung dữ liệu của bạn như sau:

def f(row):
    if row['A'] == row['B']:
        val = 0
    elif row['A'] > row['B']:
        val = 1
    else:
        val = -1
    return val

Sau đó, áp dụng nó vào khung dữ liệu của bạn truyền trong axis=1tùy chọn:

In [1]: df['C'] = df.apply(f, axis=1)

In [2]: df
Out[2]:
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

Tất nhiên, điều này không được vector hóa nên hiệu suất có thể không tốt khi được mở rộng thành một số lượng lớn các bản ghi. Tuy nhiên, tôi nghĩ nó dễ đọc hơn nhiều. Đặc biệt là xuất thân từ nền tảng SAS.

Biên tập

Đây là phiên bản vector hóa

df['C'] = np.where(
    df['A'] == df['B'], 0, np.where(
    df['A'] >  df['B'], 1, -1)) 

1
Cảm ơn bạn, tôi đang bắt đầu với gấu trúc và điều này rất hữu ích +1
nuthip

4
Điều gì sẽ xảy ra nếu tôi muốn truyền một tham số khác cùng với hàng trong hàm? Nếu tôi làm, nó nói hàng không được định nghĩa ..
Prashanth Manohar

3
Bạn phải sử dụng argstham số của .applyhàm: pandas.pydata.org/pandas-docs/stable/generated/…
Zelazny7

1
Tôi là một người dùng SAS cũ đang học Python và chắc chắn có một đường cong học tập! :-) Ví dụ, đoạn mã trên có thể được viết bằng SAS là: data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run;Rất thanh lịch và đơn giản.
RobertF

1
Một câu trả lời được xác định rõ
Sahil Nagpal

51
df.loc[df['A'] == df['B'], 'C'] = 0
df.loc[df['A'] > df['B'], 'C'] = 1
df.loc[df['A'] < df['B'], 'C'] = -1

Dễ dàng giải quyết bằng cách sử dụng lập chỉ mục. Dòng đầu tiên của mã đọc như vậy, nếu cột Abằng cột Bthì hãy tạo và đặt cột Cbằng 0.


17

Đối với mối quan hệ cụ thể này, bạn có thể sử dụng np.sign:

>>> df["C"] = np.sign(df.A - df.B)
>>> df
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

6

nhập mô tả hình ảnh ở đây

Hãy nói ở trên một là khung dữ liệu ban đầu của bạn và bạn muốn thêm một cột mới 'cũ'

Nếu tuổi lớn hơn 50 thì ta coi là già hơn = có, ngược lại là Sai

bước 1: Lấy chỉ mục của các hàng có tuổi lớn hơn 50

row_indexes=df[df['age']>=50].index

bước 2: Sử dụng .loc, chúng ta có thể gán một giá trị mới cho cột

df.loc[row_indexes,'elderly']="yes"

tương tự cho độ tuổi dưới 50

row_indexes=df[df['age']<50].index

df[row_indexes,'elderly']="no"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.