Thêm cột có giá trị không đổi vào khung dữ liệu gấu trúc [trùng lặp]


102

Đưa ra một DataFrame:

np.random.seed(0)
df = pd.DataFrame(np.random.randn(3, 3), columns=list('ABC'), index=[1, 2, 3])
df

          A         B         C
1  1.764052  0.400157  0.978738
2  2.240893  1.867558 -0.977278
3  0.950088 -0.151357 -0.103219

Cách đơn giản nhất để thêm một cột mới có chứa giá trị không đổi, ví dụ 0 là gì?

          A         B         C  new
1  1.764052  0.400157  0.978738    0
2  2.240893  1.867558 -0.977278    0
3  0.950088 -0.151357 -0.103219    0

Đây là giải pháp của tôi, nhưng tôi không biết tại sao điều này lại đặt NaN vào cột 'mới'?

df['new'] = pd.Series([0 for x in range(len(df.index))])

          A         B         C  new
1  1.764052  0.400157  0.978738  0.0
2  2.240893  1.867558 -0.977278  0.0
3  0.950088 -0.151357 -0.103219  NaN

9
nếu bạn sử dụng một chỉ mục thì không sao. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach

5
Ngoài ra, việc hiểu danh sách là hoàn toàn không cần thiết ở đây. [0] * len(df.index)
Just

@joris, ý tôi là df ['new'] = 0 hiển thị lý do thích hợp gán số không cho toàn cột, nhưng nó không giải thích tại sao lần thử đầu tiên của tôi lại chèn NaN. Điều này đã được Philip Cloud giải đáp trong câu trả lời mà tôi đã chấp nhận.
yemu

7
Đơn giản chỉ cần làmdf['new'] = 0
flow2k

Câu trả lời:


21

Lý do điều này được đặt NaNthành một cột là bởi vì df.indexIndexđối tượng bên phải của bạn khác nhau. @zach chỉ ra cách thích hợp để gán một cột số không mới. Nói chung, hãy pandascố gắng điều chỉnh các chỉ số càng nhiều càng tốt. Một nhược điểm là khi các chỉ số không được căn chỉnh, bạn sẽ nhận được NaNbất cứ nơi nào chúng không được căn chỉnh. Chơi xung quanh reindexaligncác phương pháp để có được một số trực giác cho việc căn chỉnh hoạt động với các đối tượng có các chỉ số căn chỉnh một phần, toàn bộ và không căn chỉnh tất cả. Ví dụ, đây là cách DataFrame.align()hoạt động với các chỉ số được căn chỉnh một phần:

In [7]: from pandas import DataFrame

In [8]: from numpy.random import randint

In [9]: df = DataFrame({'a': randint(3, size=10)})

In [10]:

In [10]: df
Out[10]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [11]: s = df.a[:5]

In [12]: dfa, sa = df.align(s, axis=0)

In [13]: dfa
Out[13]:
   a
0  0
1  2
2  0
3  1
4  0
5  0
6  0
7  0
8  0
9  0

In [14]: sa
Out[14]:
0     0
1     2
2     0
3     1
4     0
5   NaN
6   NaN
7   NaN
8   NaN
9   NaN
Name: a, dtype: float64

9
i didnt downvote nhưng mã của bạn thiếu ý kiến, làm cho nó khó có thể làm theo cùng với youre rằng cố gắng để đạt được trong đoạn
bồi thường

8
Điều này không thực sự trả lời câu hỏi. OP đang hỏi về cách thêm một cột mới có chứa một giá trị không đổi.
cs95

Tôi không đồng ý rằng chỉ có một câu hỏi ở đây. Có "Làm cách nào để gán một giá trị không đổi cho một cột?" cũng như "Nỗ lực của tôi để làm điều này không hoạt động theo cách X, tại sao nó hoạt động không như mong muốn?" Tôi tin rằng tôi đã giải quyết cả hai điểm, đầu tiên bằng cách đề cập đến một câu trả lời khác. Vui lòng đọc toàn bộ nội dung trong câu trả lời của tôi.
Phillip Cloud

Tôi nghĩ vấn đề là ở câu hỏi hơn là ở câu trả lời của bạn. Có hai câu hỏi riêng biệt trong bài đăng này và kết quả là cần có hai câu trả lời khác nhau để trả lời câu hỏi. Tôi tin rằng điều này đáng lẽ phải được gắn cờ là quá rộng và người đăng bài nên đặt hai câu hỏi riêng biệt.
Kevin

82

Chuyển nhượng tại chỗ siêu đơn giản: df['new'] = 0

Để sửa đổi tại chỗ, hãy thực hiện phân công trực tiếp. Nhiệm vụ này được phát bởi gấu trúc cho mỗi hàng.

df = pd.DataFrame('x', index=range(4), columns=list('ABC'))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x

df['new'] = 'y'
# Same as,
# df.loc[:, 'new'] = 'y'
df

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Lưu ý cho các cột đối tượng

Nếu bạn muốn thêm một cột danh sách trống, đây là lời khuyên của tôi:

  • Hãy xem xét không làm điều này. objectcác cột là tin xấu về mặt hiệu suất. Suy nghĩ lại cách dữ liệu của bạn được cấu trúc.
  • Cân nhắc lưu trữ dữ liệu của bạn trong một cấu trúc dữ liệu thưa thớt. Thông tin thêm: cấu trúc dữ liệu thưa thớt
  • Nếu bạn phải lưu trữ một cột danh sách, hãy đảm bảo không sao chép cùng một tham chiếu nhiều lần.

    # Wrong
    df['new'] = [[]] * len(df)
    # Right
    df['new'] = [[] for _ in range(len(df))]
    

Tạo bản sao: df.assign(new=0)

Nếu bạn cần một bản sao thay thế, hãy sử dụng DataFrame.assign:

df.assign(new='y')

   A  B  C new
0  x  x  x   y
1  x  x  x   y
2  x  x  x   y
3  x  x  x   y

Và, nếu bạn cần chỉ định nhiều cột như vậy với cùng một giá trị, điều này đơn giản như,

c = ['new1', 'new2', ...]
df.assign(**dict.fromkeys(c, 'y'))

   A  B  C new1 new2
0  x  x  x    y    y
1  x  x  x    y    y
2  x  x  x    y    y
3  x  x  x    y    y

Chỉ định nhiều cột

Cuối cùng, nếu bạn cần gán nhiều cột với các giá trị khác nhau, bạn có thể sử dụng assignvới từ điển.

c = {'new1': 'w', 'new2': 'y', 'new3': 'z'}
df.assign(**c)

   A  B  C new1 new2 new3
0  x  x  x    w    y    z
1  x  x  x    w    y    z
2  x  x  x    w    y    z
3  x  x  x    w    y    z

17

Với gấu trúc hiện đại, bạn chỉ có thể làm:

df['new'] = 0

1
Bạn có thể chỉ ra câu trả lời cụ thể nào đã lỗi thời không? Hãy để lại bình luận dưới chúng để các tác giả có cơ hội hoàn thiện hơn.
cs95

1
Fyi sự khác biệt duy nhất giữa câu trả lời này và câu trả lời cs95 (AKA, tôi) là tên và giá trị cột. Tất cả các mảnh ở đó.
cs95

1
Nó không quá lạc hậu, nhưng câu trả lời này ít dài dòng hơn những câu khác và dễ đọc hơn.
Joey

1
@Joey Không thể tranh luận với logic đó, tôi cho rằng câu trả lời này phù hợp hơn với những người chỉ muốn sao chép dán bất kỳ thứ gì sẽ hoạt động, hơn là tìm hiểu và tìm hiểu thêm về thư viện. Touche.
cs95

1
@ cs95 vâng, câu trả lời của bạn cho phép mọi người tìm hiểu thêm. Ngoài ra, df ['new'] = 0 được đánh dấu trong tiêu đề rất tốt để dễ đọc. Tôi cũng đã ủng hộ điều đó. Ít dài hơn df.apply (lambda x: 0, axis = 1)
Joey

7

Đây là một lớp lót khác sử dụng lambdas (tạo cột với giá trị không đổi = 10)

df['newCol'] = df.apply(lambda x: 10, axis=1)

trước

df
    A           B           C
1   1.764052    0.400157    0.978738
2   2.240893    1.867558    -0.977278
3   0.950088    -0.151357   -0.103219

sau

df
        A           B           C           newCol
    1   1.764052    0.400157    0.978738    10
    2   2.240893    1.867558    -0.977278   10
    3   0.950088    -0.151357   -0.103219   10

5
df['newCol'] = 10cũng là một lớp lót (và nhanh hơn). Lợi ích của việc sử dụng apply ở đây là gì?
cs95

2
không cố gắng cạnh tranh với bạn ở đây - chỉ hiển thị một cách tiếp cận thay thế.
Grant Shannon

@ cs95 Điều này rất hữu ích. Tôi muốn tạo một cột mới trong đó mỗi giá trị là một danh sách trống riêng biệt. Chỉ có phương pháp này hoạt động.
Yatharth Agarwal,

@YatharthAgarwal Tôi sẽ cung cấp cho bạn điều đó, nhưng cũng có lý do gấu trúc không được thiết kế để hoạt động tốt với các cột danh sách.
cs95,

1
@YatharthAgarwal Nếu bạn cần gán danh sách trống, đây vẫn là một giải pháp phụ vì nó sử dụng áp dụng. Hãy thửdf['new'] = [[] for _ in range(len(df))]
cs95
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.