Dodaj kolumnę ze stałą wartością do ramki danych pandy [duplikat]

102

Biorąc pod uwagę ramkę 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

Jaki jest najprostszy sposób dodania nowej kolumny zawierającej stałą wartość, np. 0?

          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

To jest moje rozwiązanie, ale nie wiem, dlaczego powoduje to umieszczenie NaN w „nowej” kolumnie?

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
yemu
źródło
9
jeśli używasz indeksu, to jest w porządku. df['new'] = pd.Series([0 for x in range(len(df.index))], index=df.index).
zach.
5
również rozumienie listy jest tutaj całkowicie niepotrzebne. po prostu zrób[0] * len(df.index)
acushner
@joris, miałem na myśli, że df ['new'] = 0 pokazuje prawidłowy powód przypisywania zer do całej kolumny, ale nie wyjaśnia, dlaczego moja pierwsza próba wstawia NaN. Na to odpowiedział Philip Cloud w odpowiedzi, którą zaakceptowałem.
yemu
7
Po prostu zróbdf['new'] = 0
flow2k

Odpowiedzi:

21

Powodem, dla którego jest to umieszczane NaNw kolumnie, jest to, że df.indexi obiekt po Indexprawej stronie są różne. @zach pokazuje właściwy sposób przypisywania nowej kolumny zer. Ogólnie rzecz biorąc, pandasstara się jak najbardziej wyrównywać indeksy. Jedną wadą jest to, że gdy indeksy nie są wyrównane, dostajesz się NaNtam, gdzie nie wyrównane. Pobaw się z metodami reindexi align, aby uzyskać intuicję dotyczącą wyrównywania, które działa z obiektami, które mają częściowo, całkowicie i nie wyrównane-wszystkie wyrównane indeksy. Na przykład oto jak DataFrame.align()działa z częściowo wyrównanymi indeksami:

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
Phillip Cloud
źródło
10
Nie głosowałem przeciw, ale w Twoim kodzie brakuje komentarzy, co utrudnia śledzenie tego, co próbujesz osiągnąć we fragmencie
zadośćuczynienie
8
To naprawdę nie odpowiada na pytanie. OP pyta, jak dodać nową kolumnę zawierającą stałą wartość.
cs95
Nie zgadzam się, że jest tylko jedno pytanie. Istnieje „Jak przypisać stałą wartość do kolumny?” a także „Moja próba zrobienia tego nie działa w sposób X, dlaczego zachowuje się nieoczekiwanie?” Wydaje mi się, że odniosłem się do obu punktów, przy czym pierwsza dotyczyła innej odpowiedzi. Przeczytaj cały tekst mojej odpowiedzi.
Phillip Cloud,
Myślę, że problem tkwi raczej w pytaniu niż w twojej odpowiedzi. W tym poście znajdują się dwa różne pytania, w wyniku czego do udzielenia odpowiedzi wymagane są dwie różne odpowiedzi. Uważam, że powinno to zostać oznaczone jako zbyt szerokie, a plakat powinien zadać dwa oddzielne pytania.
Kevin
83

Super proste przypisanie na miejscu: df['new'] = 0

W przypadku modyfikacji w miejscu wykonaj bezpośrednie przypisanie. To zadanie jest nadawane przez pandy dla każdego rzędu.

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

Uwaga dotycząca kolumn obiektów

Jeśli chcesz dodać kolumnę pustych list, oto moja rada:

  • Zastanów się, czy tego nie robić. objectkolumny to zła wiadomość pod względem wydajności. Przemyśl strukturę swoich danych.
  • Rozważ przechowywanie danych w rzadkiej strukturze danych. Więcej informacji: rzadkie struktury danych
  • Jeśli musisz przechowywać kolumnę list, nie kopiuj wielokrotnie tego samego odniesienia.

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

Generowanie kopii: df.assign(new=0)

Jeśli zamiast tego potrzebujesz kopii, użyj 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

A jeśli chcesz przypisać wiele takich kolumn o tej samej wartości, jest to tak proste, jak:

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

Przypisanie wielu kolumn

Wreszcie, jeśli chcesz przypisać wiele kolumn z różnymi wartościami, możesz użyć assignsłownika.

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
cs95
źródło
18

Dzięki nowoczesnym pandom możesz po prostu:

df['new'] = 0
Roko Mijic
źródło
1
Czy możesz wskazać, które konkretne odpowiedzi są nieaktualne? Zostawmy pod nimi komentarz, aby autorzy mieli szansę poprawić.
cs95
1
Fyi jedyną różnicą między tą odpowiedzią a odpowiedzią cs95 (AKA, ja) jest nazwa i wartość kolumny. Wszystkie kawałki są tam.
cs95
1
Nie chodzi o to, że są nieaktualne, ale ta odpowiedź jest mniej szczegółowa niż inne i łatwiejsza do odczytania.
Joey
1
@Joey Nie mogę kłócić się z tą logiką, przypuszczam, że ta odpowiedź jest bardziej odpowiednia dla osób, które chcą po prostu skopiować i wkleić wszystko, co zadziała, niż chcą zrozumieć i dowiedzieć się więcej o bibliotece. Dotyk.
cs95
1
@ cs95 tak, twoja odpowiedź pozwoli ludziom dowiedzieć się więcej. Również df ['new'] = 0 podświetlone w tytule jest dobre dla czytelności. Ja też to głosowałem. Mniej gadatliwy niż df.apply (lambda x: 0, axis = 1)
Joey
7

Oto kolejna linijka używająca lambd (utwórz kolumnę o stałej wartości = 10)

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

przed

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

po

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
Grant Shannon
źródło
5
df['newCol'] = 10jest również jednym wkładem (i jest szybszy). Jaka jest zaleta korzystania z aplikacji Apply tutaj?
cs95
2
nie próbując tu z tobą konkurować - po prostu pokazując alternatywne podejście.
Grant Shannon
@ cs95 To jest pomocne. Chciałem utworzyć nową kolumnę, w której każda wartość byłaby oddzielną pustą listą. Tylko ta metoda działa.
Yatharth Agarwal
@YatharthAgarwal Podam ci to, ale ma to również sens, biorąc pod uwagę, że pandy nie są zaprojektowane do pracy z kolumnami list.
cs95
1
@YatharthAgarwal Jeśli potrzebujesz przypisać puste listy, jest to nadal słabe rozwiązanie, ponieważ używa zastosowania. Wypróbujdf['new'] = [[] for _ in range(len(df))]
cs95,