Chèn một hàng vào khung dữ liệu gấu trúc


111

Tôi có một khung dữ liệu:

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

   A  B  C
0  5  6  7
1  7  8  9

[2 rows x 3 columns]

và tôi cần thêm hàng đầu tiên [2, 3, 4] để nhận được:

   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Tôi đã thử append()concat()thực hiện các chức năng nhưng không thể tìm thấy cách phù hợp để làm điều đó.

Làm cách nào để thêm / chèn chuỗi vào dataframe?


6
lưu ý rằng tốt hơn nên sử dụng thay s1.valuesvì sử dụng list(s1)vì bạn sẽ tạo một danh sách hoàn toàn mới bằng cách sử dụng list(s1).
acushner

7
Tôi không hiểu tại sao mọi người lại yêu quý gấu trúc đến vậy trong khi một thứ lẽ ra rất đơn giản lại đau vào mông và chậm chạp như vậy.
MattCochrane

Câu trả lời:


144

Chỉ cần gán hàng cho một chỉ mục cụ thể, sử dụng loc:

 df.loc[-1] = [2, 3, 4]  # adding a row
 df.index = df.index + 1  # shifting index
 df = df.sort_index()  # sorting by index

Và bạn nhận được, như mong muốn:

    A  B  C
 0  2  3  4
 1  5  6  7
 2  7  8  9

Xem trong tài liệu Pandas Lập chỉ mục: Cài đặt với phóng to .


2
Nếu bạn không muốn thiết lập với sự mở rộng, nhưng chèn bên trong dataframe, có một cái nhìn tại stackoverflow.com/questions/15888648/...
Foobar

6
thay đổi chỉ mục thay thế: df.sort (). reset_index (drop = True)
Meloun

2
df.sort không được dùng nữa, hãy sử dụng df.sort_index ()
GBGOLC

1
@Piotr - điều này hoạt động tốt, nhưng điều gì sẽ xảy ra khi bạn muốn sao chép một hàng từ khung dữ liệu của mình, chẳng hạn như df.loc[-1] = df.iloc[[0]]và chèn hàng đó? Khung đi kèm với lỗi cột chỉ mục được thêm vào ValueError: cannot set a row with mismatched columns (xem stackoverflow.com/questions/47340571/… )
Growler vào

5
Tôi nghĩ df.loc[-1] = [2, 3, 4] # adding a rowlà hơi gây hiểu lầm, vì -1không phải là hàng / phần tử cuối cùng, cũng như đối với các mảng Python.
flow2k

26

Không chắc bạn đã gọi như thế nào concat()nhưng nó sẽ hoạt động miễn là cả hai đối tượng đều thuộc cùng một loại. Có thể vấn đề là bạn cần truyền vectơ thứ hai của mình sang khung dữ liệu? Sử dụng df mà bạn đã xác định, các thao tác sau phù hợp với tôi:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])

Câu trả lời hay nhất ^ :)
Cam.Davidson.Pilon

23

Một cách để đạt được điều này là

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Nói chung, dễ nhất là nối các khung dữ liệu, không phải chuỗi. Trong trường hợp của bạn, vì bạn muốn hàng mới ở "trên cùng" (với id bắt đầu) và không có chức năng nào pd.prepend(), trước tiên tôi tạo khung dữ liệu mới và sau đó nối khung cũ của bạn.

ignore_indexsẽ bỏ qua chỉ mục cũ đang diễn ra trong khung dữ liệu của bạn và đảm bảo rằng hàng đầu tiên thực sự bắt đầu với chỉ mục 1thay vì bắt đầu lại với chỉ mục 0.

Tuyên bố từ chối trách nhiệm điển hình: Cetero censeo ... nối các hàng là một hoạt động khá kém hiệu quả. Nếu bạn quan tâm đến hiệu suất và bằng cách nào đó có thể đảm bảo tạo khung dữ liệu trước tiên với chỉ mục chính xác (dài hơn) và sau đó chỉ cần chèn hàng bổ sung vào khung dữ liệu, bạn chắc chắn nên làm điều đó. Xem:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

Cho đến nay, chúng tôi có những gì bạn có là df:

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

Nhưng bây giờ bạn có thể dễ dàng chèn hàng như sau. Vì không gian đã được phân bổ trước, điều này hiệu quả hơn.

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

Đó là giải pháp thay thế tốt, tôi đã cố gắng chèn chuỗi vào khung dữ liệu. Nó đủ tốt cho tôi vào lúc này.
Meloun

Tôi thích nhất là lựa chọn cuối cùng. Điều này thực sự phù hợp với những gì tôi thực sự muốn làm. Xin cảm ơn @FooBar!
Jade Cacho

13

Tôi đã tổng hợp một hàm ngắn cho phép linh hoạt hơn một chút khi chèn một hàng:

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]

    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)

    return df

có thể được rút ngắn hơn nữa thành:

def insert_row(idx, df, df_insert):
    return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

Sau đó, bạn có thể sử dụng một cái gì đó như:

df = insert_row(2, df, df_new)

đâu 2là vị trí chỉ mục dfmà bạn muốn chèn df_new.


7

Chúng ta có thể sử dụng numpy.insert. Điều này có lợi thế về tính linh hoạt. Bạn chỉ cần chỉ định chỉ mục bạn muốn chèn vào.

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

pd.DataFrame(np.insert(df.values, 0, values=[2, 3, 4], axis=0))

    0   1   2
0   2   3   4
1   5   6   7
2   7   8   9

Đối với np.insert(df.values, 0, values=[2, 3, 4], axis=0), 0 cho hàm biết vị trí / chỉ mục bạn muốn đặt các giá trị mới.


6

điều này có vẻ quá đơn giản nhưng thật khó tin khi một chức năng chèn hàng mới đơn giản không được tích hợp sẵn. Tôi đã đọc rất nhiều về cách thêm một df mới vào bản gốc, nhưng tôi đang tự hỏi liệu điều này có nhanh hơn không.

df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]

Ý của bạn là "thêm một df mới" hay chỉ "thêm một hàng mới", như mã của bạn hiển thị?
smci

xin lỗi câu của tôi không rõ ràng. tôi đã đọc các giải pháp của người khác nối / nối một khung dữ liệu hoàn toàn mới chỉ với một hàng. nhưng trong giải pháp của tôi, nó chỉ là một hàng duy nhất trong khung dữ liệu hiện có mà không cần tạo khung dữ liệu bổ sung
Aaron Melgar

6

Dưới đây sẽ là cách tốt nhất để chèn một hàng vào khung dữ liệu gấu trúc mà không cần sắp xếp và gửi lại chỉ mục:

import pandas as pd

df = pd.DataFrame(columns=['a','b','c'])

def insert(df, row):
    insert_loc = df.index.max()

    if pd.isna(insert_loc):
        df.loc[0] = row
    else:
        df.loc[insert_loc + 1] = row

insert(df,[2,3,4])
insert(df,[8,9,0])
print(df)

tại sao bạn lại nói đây là cách tốt nhất?
Yuca

thì sẽ rất tốt nếu bạn cung cấp bằng chứng để hỗ trợ cho tuyên bố đó, bạn đã dành thời gian chưa?
Yuca

1
bạn có thể sử dụng pd.isna để tránh nhập khẩu NumPy
kato2

1

concat()dường như nhanh hơn một chút so với việc chèn và lập chỉ mục hàng cuối cùng. Trong trường hợp ai đó sẽ thắc mắc về tốc độ của hai cách tiếp cận hàng đầu:

In [x]: %%timeit
     ...: df = pd.DataFrame(columns=['a','b'])
     ...: for i in range(10000):
     ...:     df.loc[-1] = [1,2]
     ...:     df.index = df.index + 1
     ...:     df = df.sort_index()

17,1 s ± 705 ms mỗi vòng (trung bình ± std. Dev. Của 7 lần chạy, mỗi lần 1 vòng)

In [y]: %%timeit
     ...: df = pd.DataFrame(columns=['a', 'b'])
     ...: for i in range(10000):
     ...:     df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df])

6,53 s ± 127 ms mỗi vòng (trung bình ± std. Dev. Của 7 lần chạy, mỗi vòng 1 lần)


1

Rất đơn giản để thêm một hàng vào gấu trúc DataFrame:

  1. Tạo một từ điển Python thông thường với các tên cột giống như của bạn Dataframe;

  2. Sử dụng pandas.append()phương thức và nhập tên từ điển của bạn, .append()phương thức ở đâu trên các cá thể DataFrame;

  3. Thêm ignore_index=Truengay sau tên từ điển của bạn.


Đây có lẽ là lựa chọn thích hợp nhất (khoảng năm 2020).
David Golembiowski

0

Bạn có thể chỉ cần nối hàng vào cuối DataFrame, sau đó điều chỉnh chỉ mục.

Ví dụ:

df = df.append(pd.DataFrame([[2,3,4]],columns=df.columns),ignore_index=True)
df.index = (df.index + 1) % len(df)
df = df.sort_index()

Hoặc sử dụng concatnhư:

df = pd.concat([pd.DataFrame([[1,2,3,4,5,6]],columns=df.columns),df],ignore_index=True)

-1

Cách đơn giản nhất để thêm một hàng trong khung dữ liệu gấu trúc là:

DataFrame.loc[ location of insertion ]= list( )

Thí dụ :

DF.loc[ 9 ] = [ ´Pepe , 33, ´Japan ]

NB: độ dài của danh sách của bạn phải khớp với độ dài của khung dữ liệu.


đã lừa cho tôi!
Sam Shaw
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.