Gấu trúc - Nhận giá trị hàng đầu tiên của một cột nhất định


300

Đây có vẻ như là một câu hỏi dễ dàng đến nực cười ... nhưng tôi không thấy câu trả lời dễ dàng mà tôi đang mong đợi.

Vậy, làm thế nào để tôi có được giá trị ở hàng thứ n của một cột nhất định trong Pandas? (Tôi đặc biệt quan tâm đến hàng đầu tiên, nhưng cũng sẽ quan tâm đến một thực tiễn tổng quát hơn).

Ví dụ: giả sử tôi muốn lấy giá trị 1,2 trong Btime làm biến.

Cách đúng đắn để làm điều này là gì?

df_test =

  ATime   X   Y   Z   Btime  C   D   E
0    1.2  2  15   2    1.2  12  25  12
1    1.4  3  12   1    1.3  13  22  11
2    1.5  1  10   6    1.4  11  20  16
3    1.6  2   9  10    1.7  12  29  12
4    1.9  1   1   9    1.9  11  21  19
5    2.0  0   0   0    2.0   8  10  11
6    2.4  0   0   0    2.4  10  12  15

7
Nếu bạn chỉ đơn giản chỉ muốn hàng đầu tiên thì df_test.head(1)sẽ hoạt động, hình thức tổng quát hơn là sử dụng ilocnhư được trả lời bởi unutbu
EdChum

1
Bạn có muốn chỉ là giá trị 1.2? hoặc Sê-ri có độ dài 1 mà bạn nhận được df_test.head(1), cũng sẽ chứa chỉ mục? Để có được giá trị làm df_test.head(1).item(), hoặc tolist()sau đó cắt lát.
smci

Câu trả lời:


472

Để chọn ithhàng, sử dụngiloc :

In [31]: df_test.iloc[0]
Out[31]: 
ATime     1.2
X         2.0
Y        15.0
Z         2.0
Btime     1.2
C        12.0
D        25.0
E        12.0
Name: 0, dtype: float64

Để chọn giá trị thứ i trong Btimecột bạn có thể sử dụng:

In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2

Có một sự khác biệt giữa df_test['Btime'].iloc[0](được khuyến nghị) và df_test.iloc[0]['Btime']:

DataFrames lưu trữ dữ liệu trong các khối dựa trên cột (trong đó mỗi khối có một dtype duy nhất). Nếu bạn chọn theo cột trước, một khung nhìn có thể được trả về (nhanh hơn trả về một bản sao) và dtype ban đầu được giữ nguyên. Ngược lại, nếu bạn chọn theo hàng trước và nếu DataFrame có các cột của các loại khác nhau, thì Pandas sao chép dữ liệu vào một chuỗi kiểu đối tượng mới. Vì vậy, chọn cột nhanh hơn một chút so với chọn hàng. Vì vậy, mặc dù df_test.iloc[0]['Btime']hoạt động, df_test['Btime'].iloc[0]là một chút hiệu quả hơn.

Có một sự khác biệt lớn giữa hai khi phân công. df_test['Btime'].iloc[0] = xảnh hưởng df_test, nhưng df_test.iloc[0]['Btime'] có thể không. Xem dưới đây để giải thích lý do tại sao. Bởi vì một sự khác biệt tinh tế trong thứ tự lập chỉ mục tạo ra sự khác biệt lớn trong hành vi, tốt hơn là sử dụng phân công lập chỉ mục duy nhất:

df.iloc[0, df.columns.get_loc('Btime')] = x

df.iloc[0, df.columns.get_loc('Btime')] = x (khuyên dùng):

Cách được đề xuất để gán các giá trị mới cho DataFrame là tránh lập chỉ mục chuỗi và thay vào đó sử dụng phương thức được hiển thị bởi andrew ,

df.loc[df.index[n], 'Btime'] = x

hoặc là

df.iloc[n, df.columns.get_loc('Btime')] = x

Phương thức sau nhanh hơn một chút, vì df.locphải chuyển đổi nhãn hàng và cột thành chỉ mục vị trí, do đó, cần ít chuyển đổi hơn nếu bạn sử dụng df.ilocthay thế.


df['Btime'].iloc[0] = x hoạt động, nhưng không được khuyến khích:

Mặc dù điều này hoạt động, nhưng nó đang tận dụng cách thức DataFrames hiện đang được triển khai. Không có gì đảm bảo rằng Pandas phải làm việc theo cách này trong tương lai. Cụ thể, nó đang lợi dụng thực tế là (hiện tại) df['Btime']luôn trả về một chế độ xem (không phải là bản sao) để df['Btime'].iloc[n] = xcó thể được sử dụng để gán giá trị mới tại vị trí thứ n của Btimecột df.

Vì Pandas không đảm bảo rõ ràng về việc khi nào người lập chỉ mục trả về chế độ xem so với bản sao, các bài tập sử dụng lập chỉ mục chuỗi thường luôn tăng SettingWithCopyWarningngay cả trong trường hợp này, bài tập thành công trong việc sửa đổi df:

In [22]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [24]: df['bar'] = 100
In [25]: df['bar'].iloc[0] = 99
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

In [26]: df
Out[26]: 
  foo  bar
0   A   99  <-- assignment succeeded
2   B  100
1   C  100

df.iloc[0]['Btime'] = x không hoạt động:

Ngược lại, gán với df.iloc[0]['bar'] = 123không hoạt động vì df.iloc[0]đang trả lại một bản sao:

In [66]: df.iloc[0]['bar'] = 123
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

In [67]: df
Out[67]: 
  foo  bar
0   A   99  <-- assignment failed
2   B  100
1   C  100

Cảnh báo : Tôi đã đề nghị trước đây df_test.ix[i, 'Btime']. Nhưng điều này không được đảm bảo để cung cấp cho bạn ithgiá trị vì ixcố gắng lập chỉ mục theo nhãn trước khi cố gắng lập chỉ mục theo vị trí . Vì vậy, nếu DataFrame có một chỉ số nguyên không theo thứ tự được sắp xếp bắt đầu từ 0, thì việc sử dụng ix[i]sẽ trả về hàng được gắn nhãn i thay vì ithhàng. Ví dụ,

In [1]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])

In [2]: df
Out[2]: 
  foo
0   A
2   B
1   C

In [4]: df.ix[1, 'foo']
Out[4]: 'C'

1
@CristianCiupitu: DataFrames lưu trữ dữ liệu trong các khối dựa trên cột (trong đó mỗi khối có một dtype duy nhất). Ngược lại, nếu bạn chọn theo hàng trước và nếu DataFrame có các cột của các loại khác nhau, thì Pandas sao chép dữ liệu vào một chuỗi kiểu đối tượng mới. Vì vậy, chọn cột nhanh hơn một chút so với chọn hàng. Vì vậy, mặc dù df_test.iloc[0]['Btime']hoạt động, df_test.iloc['Btime'][0]là một chút hiệu quả hơn.
unutbu

@unutbu, được df['Btime'].iloc[0]ưa thích hơn df['Btime'].values[0]? tôi có thể thấy từ tài liệu có nội dung "Cảnh báo: Chúng tôi khuyên bạn nên sử dụng Series.array hoặc Series.to_numpy (), tùy thuộc vào việc bạn cần tham chiếu đến dữ liệu cơ bản hay mảng NumPy." nhưng tôi không chắc chính xác điều đó có nghĩa là gì
aydow

28

Lưu ý rằng câu trả lời từ @unutbu sẽ chính xác cho đến khi bạn muốn đặt giá trị thành một cái gì đó mới, thì nó sẽ không hoạt động nếu khung dữ liệu của bạn là dạng xem.

In [4]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [5]: df['bar'] = 100
In [6]: df['bar'].iloc[0] = 99
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas-0.16.0_19_g8d2818e-py2.7-macosx-10.9-x86_64.egg/pandas/core/indexing.py:118: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

Một cách tiếp cận khác sẽ luôn hoạt động với cả cài đặt và nhận là:

In [7]: df.loc[df.index[0], 'foo']
Out[7]: 'A'
In [8]: df.loc[df.index[0], 'bar'] = 99
In [9]: df
Out[9]:
  foo  bar
0   A   99
2   B  100
1   C  100

1
Tôi đang lặp qua một loạt các tệp .csv và đọc giá trị đầu tiên của một cột nhất định trong mỗi cột. Vì một số lý do mà tôi không thể giải thích thay vì trả về giá trị, đôi khi nó trả về chỉ mục cùng với giá trị gây rối cho quá trình xử lý. Tôi đã viện đến df.col.unique () [0].
chim sẻ

15

Một cách khác để làm điều này:

first_value = df['Btime'].values[0]

Cách này dường như nhanh hơn so với sử dụng .iloc:

In [1]: %timeit -n 1000 df['Btime'].values[20]
5.82 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [2]: %timeit -n 1000 df['Btime'].iloc[20]
29.2 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

12
  1. df.iloc[0].head(1) - Dữ liệu đầu tiên chỉ được đặt từ toàn bộ hàng đầu tiên.
  2. df.iloc[0] - Toàn bộ hàng đầu tiên trong cột.

8

Nói chung, nếu bạn muốn chọn N hàng đầu tiên từ cột J từ pandas dataframecách tốt nhất để làm điều này là:

data = dataframe[0:N][:,J]

2
@anis: Đối với mục đích này, bạn nên viết một câu hỏi mới để yêu cầu giải pháp tổng quát hơn và tự mình trả lời nó.
jonathan.scholbach

3

Ví dụ, để lấy giá trị từ cột 'test' và hàng 1, nó hoạt động như

df[['test']].values[0][0]

như chỉ df[['test']].values[0]trả lại một mảng


1

Một cách khác để có được hàng đầu tiên và bảo toàn chỉ mục:

x = df.first('d') # Returns the first day. '3d' gives first three days.
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.