Hiểu tại chỗ = Đúng


104

Trong pandasthư viện nhiều lần có một tùy chọn để thay đổi đối tượng tại chỗ, chẳng hạn như với câu lệnh sau ...

df.dropna(axis='index', how='all', inplace=True)

Tôi tò mò những gì đang được trả về cũng như cách đối tượng được xử lý khi inplace=Trueđược chuyển qua so với khi nào inplace=False.

Tất cả các hoạt động có sửa đổi selfkhi inplace=Truenào không? Và khi nào inplace=Falsemột đối tượng mới được tạo ngay lập tức chẳng hạn như new_df = selfvà sau đó new_dfđược trả về?


13
Có, inplace=Truetrả về trả None inplace=Falsevề một bản sao của đối tượng với thao tác được thực hiện. Các tài liệu khá rõ ràng về điều này, có điều gì đó gây nhầm lẫn với một phần cụ thể? SpeficallyIf True, do operation inplace and return None.
EdChum

Tôi subclassing đối tượng DataFrame và với một hoạt động như merge nó dường như không thể làm điều đó INPLACE ... self = self.merge(new_df, how='left', on='column2' Tôi không chắc chắn rằng nó có thể tự phân công lại
Aran Freel

1
Bạn đúng rằng DataFrame.merge không có inplaceđối số. Nó trả về một DataFrame, vì vậy không có vấn đề gì khi gán lại.
JAV

Ai đó cũng có thể nêu bật những lợi thế của việc sử dụng nó trong điều kiện tiêu thụ tài nguyên?
markroxor

2
@markroxor Thực sự không có nhiều. Trong một số trường hợp, inplacehành động có thể nhanh hơn một chút vì bạn không thực sự phải trả lại bản sao kết quả. Nhưng đó là về nó. Có nhiều lý do hơn để không sử dụng nó.
cs95

Câu trả lời:


96

Khi inplace=Trueđược thông qua, dữ liệu được đổi tên tại chỗ (nó không trả về gì), vì vậy bạn sẽ sử dụng:

df.an_operation(inplace=True)

Khi inplace=Falseđược chuyển (đây là giá trị mặc định, vì vậy không cần thiết), thực hiện thao tác và trả về một bản sao của đối tượng, vì vậy bạn sẽ sử dụng:

df = df.an_operation(inplace=False) 

Tôi có đúng khi nghĩ rằng đó inplacechỉ là một lựa chọn cho các phương pháp làm thay đổi dữ liệu hiện có, nhưng không phải cho các phương pháp 'định hình lại' dữ liệu. Ví dụ: tôi có thể .set_index (inplace = True) vì điều này áp dụng giá trị cho chỉ mục hiện có, nhưng không thể .reindex (inplace = True) vì điều này có thể tạo thêm hàng trên DataFrame không tồn tại trong mảng trước đó ?
ac24

4
Phương thức .dropna()chấp nhận inplace=Truevà chắc chắn nhất có thể định hình lại khung dữ liệu, vì vậy không.
jorijnsmit

3
Bạn phải cẩn thận ở đây. @ ac24 thực ra ít nhiều đúng. Trong khi dropnatrả về khung dữ liệu có hình dạng khác, nó không thực sự định hình lại dữ liệu cơ bản - nó chỉ trả về một mặt nạ trên nó (khi nào inplace=False), điều này có thể dẫn đến điều đáng sợ SettingWithCopyWarning. Chỉ khi không còn tham chiếu đến mảng giá trị cũ thì gấu trúc mới định hình lại theo mặt nạ. Quy tắc ngón tay cái tốt hơn là: inplacekhả dụng khi thao tác không yêu cầu cấp phát dãy giá trị dự phòng mới.
BallpointBen

46

Cách tôi sử dụng nó là

# Have to assign back to dataframe (because it is a new copy)
df = df.some_operation(inplace=False) 

Hoặc là

# No need to assign back to dataframe (because it is on the same copy)
df.some_operation(inplace=True)

PHẦN KẾT LUẬN:

 if inplace is False
      Assign to a new variable;
 else
      No need to assign

5
Xin chào @Nabin, Đó là cách quá rõ ràng cho bất kỳ ai làm việc trên Pandas và Numpy :-)
Vetrivel PS

44

Ở gấu trúc, inplace = True có bị coi là có hại hay không?

TLDR; Vâng vâng nó là.

  • inplace, trái với những gì tên ngụ ý, thường không ngăn cản việc tạo bản sao và (hầu như) không bao giờ mang lại bất kỳ lợi ích hiệu suất nào
  • inplace không hoạt động với chuỗi phương thức
  • inplace là một cạm bẫy phổ biến đối với người mới bắt đầu, vì vậy việc loại bỏ tùy chọn này sẽ đơn giản hóa API

Tôi không khuyên bạn nên đặt thông số này vì nó phục vụ cho mục đích nhỏ . Hãy xem vấn đề GitHub này đề xuất inplaceđối số không được chấp nhận trên toàn ứng dụng.

Đó là một quan niệm sai lầm phổ biến rằng việc sử dụng inplace=Truesẽ dẫn đến mã hiệu quả hơn hoặc được tối ưu hóa. Trong thực tế, hoàn toàn không có lợi ích về hiệu suất khi sử dụng inplace=True. Cả tại chỗ và out-of-nơi các phiên bản tạo ra một bản sao của dữ liệu nào , với phiên bản tại chỗ tự động gán bản sao trở lại.

inplace=Truelà một cạm bẫy phổ biến cho người mới bắt đầu. Ví dụ, nó có thể kích hoạtSettingWithCopyWarning :

df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})

df2 = df[df['a'] > 1]
df2['b'].replace({'x': 'abc'}, inplace=True)
# SettingWithCopyWarning: 
# A value is trying to be set on a copy of a slice from a DataFrame

Gọi một hàm trên cột DataFrame inplace=True có thể hoạt động hoặc không . Điều này đặc biệt đúng khi liên quan đến lập chỉ mục chuỗi.

Như thể các vấn đề được mô tả ở trên là không đủ, inplace=Truecũng cản trở chuỗi phương thức . Trái ngược với công việc của

result = df.some_function1().reset_index().some_function2()

Như trái ngược với

temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()

Điều trước đây cho thấy khả năng tổ chức và đọc mã tốt hơn.


Một tuyên bố hỗ trợ khác là API cho set_axisgần đây đã được thay đổi để inplacegiá trị mặc định được chuyển từ True thành False. Xem GH27600 . Các nhà phát triển làm rất tốt!


Chắc chắn inplace=Truekhông hoạt động với chuỗi, v.v. nhưng điều đó hiển nhiên là bạn hiểu nó đang làm gì về mặt khái niệm. Cá nhân tôi thấy nó gọn gàng hơn một chút để tránh bị phân công- Bạn cũng có ủng hộ việc xóa list.sortv.v. khỏi thư viện chuẩn không?
Chris_Rands

4
Tôi không nghĩ đó là một sự so sánh công bằng. Có một số lợi ích rõ ràng của việc sử dụng list.sort so với sắp xếp. Tương tự với các chức năng tại chỗ khác. Không có lợi ích thực sự ở đây, phương thức chuỗi phổ biến hơn nhiều ở gấu trúc và dù sao cũng có kế hoạch cho việc phản đối lập luận này.
cs95 10/12/19

Tôi cũng thấy nó gọn gàng hơn một chút để tránh chuyển nhượng: ví dụ, python list.append()cũng được cung cấp tại chỗ, trong khi pandas df.append thì không (và thậm chí không hỗ trợ inplace), điều này khiến tôi khó chịu. Đó là lý do tại sao tôi muốn biết, chỉ để hiểu những lợi ích thực sự là gì - những lợi ích rõ ràng của việc sử dụng list.sort so với sắp xếp, ngoài việc tránh chuyển nhượng là gì? Mặt khác, tôi nghĩ rằng có lợi ích thực sự ở đây - tôi có thể tránh được nhiệm vụ, nơi cá nhân tôi thấy nó dễ đọc hơn.
sdbbs

1
@sdbbs list.append()nối vào danh sách hiện có. df.appendtạo một bản sao dữ liệu của bạn (không quan trọng bạn có 5 hàng hay 5 triệu), sau đó thêm một hàng mới vào bản sao của bạn, rồi trả lại. Bạn nghĩ điều gì có ý nghĩa hơn? Còn đối với df.append, TRÁNH NHIỀU KHI CÓ THỂ . Tôi không nghĩ rằng đó là một ví dụ tốt để tranh luận cho inplace = True, tôi thậm chí không nghĩ rằng hàm đó có một vị trí trong API.
cs95

6

Các inplacetham số:

df.dropna(axis='index', how='all', inplace=True)

trong Pandasvà ở các khoản chung:

1. Pandas tạo một bản sao của dữ liệu gốc

2. ... thực hiện một số tính toán trên nó

3. ... gán kết quả cho dữ liệu gốc.

4. ... xóa bản sao.

Như bạn có thể đọc phần còn lại của câu trả lời của tôi ở bên dưới, chúng ta vẫn có thể có lý do chính đáng để sử dụng tham số này, tức là inplace operations, nhưng chúng ta nên tránh nó nếu có thể, vì nó tạo ra nhiều vấn đề hơn, như:

1. Mã của bạn sẽ khó gỡ lỗi hơn (Thực ra SettingwithCopyWarning là viết tắt của cảnh báo bạn về vấn đề có thể xảy ra này)

2. Xung đột với chuỗi phương thức


Vì vậy, có thậm chí trường hợp khi chúng ta nên sử dụng nó chưa?

Chắc chắn là có. Nếu chúng ta sử dụng gấu trúc hoặc bất kỳ công cụ nào để xử lý tập dữ liệu khổng lồ, chúng ta có thể dễ dàng đối mặt với tình huống, nơi một số dữ liệu lớn có thể tiêu tốn toàn bộ bộ nhớ của chúng ta. Để tránh tác dụng không mong muốn này, chúng ta có thể sử dụng một số kỹ thuật như chuỗi phương pháp :

(
    wine.rename(columns={"color_intensity": "ci"})
    .assign(color_filter=lambda x: np.where((x.hue > 1) & (x.ci > 7), 1, 0))
    .query("alcohol > 14 and color_filter == 1")
    .sort_values("alcohol", ascending=False)
    .reset_index(drop=True)
    .loc[:, ["alcohol", "ci", "hue"]]
)

làm cho mã của chúng tôi nhỏ gọn hơn (mặc dù khó hiểu và gỡ lỗi hơn) và tiêu thụ ít bộ nhớ hơn vì các phương thức chuỗi hoạt động với các giá trị trả về của phương thức khác, do đó chỉ tạo ra một bản sao dữ liệu đầu vào. Chúng ta có thể thấy rõ ràng rằng chúng ta sẽ sử dụng 2 x bộ nhớ dữ liệu gốc sau các hoạt động này.

Hoặc chúng ta có thể sử dụng inplacetham số (mặc dù khó hiểu và gỡ lỗi hơn) mức tiêu thụ bộ nhớ của chúng ta sẽ là 2 x dữ liệu gốc , nhưng mức tiêu thụ bộ nhớ của chúng ta sau thao tác này vẫn là 1 x dữ liệu gốc , điều mà nếu ai đó bất cứ khi nào làm việc với các bộ dữ liệu lớn biết chính xác có thể là lợi ích lớn.


Kết luận cuối cùng:

Tránh sử dụng inplacetham số trừ khi bạn không làm việc với dữ liệu lớn và lưu ý các vấn đề có thể xảy ra trong trường hợp vẫn sử dụng tham số.


2

Lưu nó vào cùng một biến

data["column01"].where(data["column01"]< 5, inplace=True)

Lưu nó vào một biến riêng biệt

data["column02"] = data["column01"].where(data["column1"]< 5)

Tuy nhiên, bạn luôn có thể ghi đè biến

data["column01"] = data["column01"].where(data["column1"]< 5)

FYI: Mặc định inplace = False


1

Khi cố gắng thực hiện các thay đổi đối với khung dữ liệu Pandas bằng một hàm, chúng tôi sử dụng 'inplace = True' nếu chúng tôi muốn thực hiện các thay đổi đối với khung dữ liệu. Do đó, dòng đầu tiên trong đoạn mã sau thay đổi tên của cột đầu tiên trong 'df' thành 'Lớp'. Chúng ta cần gọi cơ sở dữ liệu nếu chúng ta muốn xem cơ sở dữ liệu kết quả.

df.rename(columns={0: 'Grades'}, inplace=True)
df

Chúng tôi sử dụng 'inplace = False' (đây cũng là giá trị mặc định) khi chúng tôi không muốn cam kết các thay đổi mà chỉ in cơ sở dữ liệu kết quả. Vì vậy, trên thực tế, một bản sao của cơ sở dữ liệu gốc với những thay đổi đã cam kết sẽ được in ra mà không làm thay đổi cơ sở dữ liệu gốc.

Để rõ ràng hơn, các mã sau thực hiện tương tự:

#Code 1
df.rename(columns={0: 'Grades'}, inplace=True)
#Code 2
df=df.rename(columns={0: 'Grades'}, inplace=False}

0

inplace=True được sử dụng tùy thuộc vào việc bạn có muốn thực hiện thay đổi đối với df gốc hay không.

df.drop_duplicates()

sẽ chỉ thực hiện chế độ xem các giá trị bị giảm nhưng không thực hiện bất kỳ thay đổi nào đối với df

df.drop_duplicates(inplace  = True)

sẽ giảm giá trị và thực hiện thay đổi đối với df.

Hi vọng điêu nay co ich.:)


0

inplace=Truelàm cho hàm không tinh khiết. Nó thay đổi khung dữ liệu ban đầu và trả về Không có. Trong trường hợp đó, Bạn phá vỡ chuỗi DSL. Vì hầu hết các hàm khung dữ liệu trả về khung dữ liệu mới, bạn có thể sử dụng DSL một cách thuận tiện. Giống

df.sort_values().rename().to_csv()

Gọi hàm với inplace=Truetrả về Không có và chuỗi DSL bị hỏng. Ví dụ

df.sort_values(inplace=True).rename().to_csv()

sẽ ném NoneType object has no attribute 'rename'

Một cái gì đó tương tự với sắp xếp và sắp xếp tích hợp sẵn của python. lst.sort()trả về Nonesorted(lst)trả về một danh sách mới.

Nói chung, không sử dụng inplace=Truetrừ khi bạn có lý do cụ thể để làm như vậy. Khi bạn phải viết mã gán lại như df = df.sort_values(), hãy thử đính kèm lệnh gọi hàm trong chuỗi DSL, ví dụ:

df = pd.read_csv().sort_values()...

cung cấp mã làm việc chính xác với định dạng phù hợp sẽ thực sự giúp người dùng hiểu câu trả lời của bạn nhanh hơn. Yêu cầu bạn làm tương tự. Tôi không phải là chuyên gia về gấu trúc, vì vậy không thể định dạng lại câu trả lời của bạn, nhưng nó rất được khuyến khích,
Anand Vaidya

0

Theo kinh nghiệm của tôi về gấu trúc, tôi muốn trả lời.

Đối số 'inplace = True' là viết tắt của khung dữ liệu phải thực hiện các thay đổi vĩnh viễn, ví dụ:

    df.dropna(axis='index', how='all', inplace=True)

thay đổi cùng một khung dữ liệu (vì gấu trúc này tìm thấy các mục nhập NaN trong chỉ mục và loại bỏ chúng). Nếu chúng ta cố gắng

    df.dropna(axis='index', how='all')

pandas hiển thị khung dữ liệu với những thay đổi mà chúng tôi thực hiện nhưng sẽ không sửa đổi khung dữ liệu ban đầu 'df'.


0

Nếu bạn không sử dụng inplace = True hoặc bạn sử dụng inplace = False, về cơ bản bạn sẽ nhận lại được một bản sao.

Ví dụ:

testdf.sort_values(inplace=True, by='volume', ascending=False)

sẽ thay đổi cấu trúc với dữ liệu được sắp xếp theo thứ tự giảm dần.

sau đó:

testdf2 = testdf.sort_values( by='volume', ascending=True)

sẽ tạo bản sao testdf2. tất cả các giá trị sẽ giống nhau nhưng sắp xếp sẽ được đảo ngược và bạn sẽ có một đối tượng độc lập.

sau đó đưa ra một cột khác, nói LongMA và bạn làm:

testdf2.LongMA = testdf2.LongMA -1

cột LongMA trong testdf sẽ có các giá trị ban đầu và testdf2 sẽ có các giá trị đã phân loại.

Điều quan trọng là phải theo dõi sự khác biệt khi chuỗi tính toán phát triển và các bản sao của khung dữ liệu có vòng đời riêng của chúng.


0

Có, trong Pandas, chúng ta có nhiều hàm có tham số inplacenhưng theo mặc định thì nó được gán cho False.

Vì vậy, khi bạn làm điều df.dropna(axis='index', how='all', inplace=False)đó nghĩ rằng bạn không muốn thay đổi nguyên tác DataFrame, do đó, thay vào đó nó sẽ tạo một bản sao mới cho bạn với những thay đổi cần thiết.

Tuy nhiên, khi bạn thay đổi inplacetham số thànhTrue

Sau đó, nó tương đương với việc nói rõ ràng rằng tôi không muốn có một bản sao mới DataFramethay vào đó hãy thực hiện các thay đổi trênDataFrame

Điều này buộc trình thông dịch Python không tạoDataFrame

Nhưng bạn cũng có thể tránh sử dụng inplacetham số bằng cách gán lại kết quả cho DataFrame gốc

df = df.dropna(axis='index', how='all')

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.