빈 Pandas DataFrame을 만든 다음 채우시겠습니까?


461

나는 판다 데이터 프레임 문서에서 시작하고 있습니다 : http://pandas.pydata.org/pandas-docs/stable/dsintro.html

시계열 종류의 계산 값으로 DataFrame을 반복적으로 채우고 싶습니다. 따라서 기본적으로 열 A, B 및 타임 스탬프 행, 모두 0 또는 모든 NaN으로 DataFrame을 초기화하고 싶습니다.

그런 다음 초기 값을 추가 하고이 데이터를 검토하여 이전의 행에서 새 행을 계산합니다 row[A][t] = row[A][t-1]+1.

현재 아래와 같이 코드를 사용하고 있지만 그 방법은 추악하다고 생각되며 DataFrame을 사용하여 직접 수행하거나 일반적인 방법으로 더 좋은 방법이 있어야합니다. 참고 : Python 2.7을 사용하고 있습니다.

import datetime as dt
import pandas as pd
import scipy as s

if __name__ == '__main__':
    base = dt.datetime.today().date()
    dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
    dates.sort()

    valdict = {}
    symbols = ['A','B', 'C']
    for symb in symbols:
        valdict[symb] = pd.Series( s.zeros( len(dates)), dates )

    for thedate in dates:
        if thedate > dates[0]:
            for symb in valdict:
                valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]

    print valdict

6
DataFrame을 늘리지 마십시오! 파이썬 목록에 추가 한 다음 메모리와 성능 측면에서 마지막에 DataFrame으로 변환하는 것이 항상 저렴합니다.
cs95

@ cs95 .appendpd에서 목록을 추가하는 것과 기능적으로 다른 점은 무엇입니까 ? 나는 .append판다에서 전체 데이터 세트를 새로운 객체에 복사한다는 것을 알고 있습니다 . 파이썬은 다르게 작동합니까?
Lamma

@Lamma 아래 답변에서 자세한 내용을 찾으십시오. df를 추가 할 때 기존의 프레임을 사용하는 대신 메모리에 새로운 DataFrame이 생성됩니다.
cs95

답변:


330

다음은 몇 가지 제안입니다.

date_range색인에 사용하십시오 .

import datetime
import pandas as pd
import numpy as np

todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')

columns = ['A','B', 'C']

참고 : NaN간단히 다음 과 같이 작성하여 빈 DataFrame ( s 포함)을 만들 수 있습니다 .

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

데이터에 대해 이러한 유형의 계산을 수행하려면 numpy 배열을 사용하십시오.

data = np.array([np.arange(10)]*3).T

따라서 DataFrame을 만들 수 있습니다.

In [10]: df = pd.DataFrame(data, index=index, columns=columns)

In [11]: df
Out[11]: 
            A  B  C
2012-11-29  0  0  0
2012-11-30  1  1  1
2012-12-01  2  2  2
2012-12-02  3  3  3
2012-12-03  4  4  4
2012-12-04  5  5  5
2012-12-05  6  6  6
2012-12-06  7  7  7
2012-12-07  8  8  8
2012-12-08  9  9  9

2
pd.date_range ()가 작동하지 않습니다. 나는 일식 자동 완성에서 DateRange로 시도했지만 문자열과 날짜 형식으로 작동합니다. 전반적인 접근 방식은 효과적입니다 (색인을 다른 것으로 변경했습니다).
Matthias Kauer

2
date_range는 날짜 시간 인덱스를 생성하는 팩토리 함수 이며 0.8.0의 새로운 기능이었습니다. 버그 수정 및 새로운 기능이 많이있는 최신 안정 릴리스 (0.9.1)로 업그레이드하는 것이 좋습니다. :)
Andy Hayden

26
내 경험상 NaN으로 채워진 필요한 크기의 데이터 프레임을 만든 다음 값을 채우는 것은 indexx 0차원 ( columns = []) 으로 데이터 프레임을 만들고 루프의 각 턴에 하나의 열을 연결 하는 것보다 훨씬 느립니다 . df[col_name] = pandas.Series([...])열 이름을 반복하는 루프를 의미 합니다. 전자의 경우에는 메모리 할당에 시간이 걸리는 것이 아니라 NaN을 새로운 값으로 교체하는 것이 매우 느리게 보입니다.
초 deeenes

5
@deeenes 확실히. 이 대답은 아마도 더 명확해야합니다-NaN의 빈 데이터 프레임을 만드는 경우는 거의 없습니다.
Andy Hayden

1
이 답변에 따라 stackoverflow.com/a/30267881/2302569 fillna의 결과를 할당하거나 param inplace = True
JayJay

169

빈 데이터 프레임을 만들고 나중에 들어오는 데이터 프레임으로 채우려면 다음을 시도하십시오.

newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional 

이 예에서는이 팬더 문서 를 사용하여 새 데이터 프레임을 만든 다음 추가 를 사용 하고 있습니다. 를 하여 oldDF의 데이터로 newDF에 씁니다.

둘 이상의 oldDF 에서이 newDF에 새 데이터를 계속 추가 해야하는 경우 for 루프를 사용하여 pandas 를 반복합니다 .DataFrame.append ()


14
제발 참고 append(유사 concat) 사본 새 개체에 대한 전체 데이터 세트마다, 따라서, 반복 수를 추가하고 주요 성능 저하의 원인이됩니다. 자세한 내용은 다음을 참조하십시오 : pandas.pydata.org/pandas-docs/stable/merging.html
MoustafaAAtta

4
@MoustafaAAtta 데이터 프레임에 반복적으로 데이터를 추가하는 대안은 무엇입니까?
MysteryGuy

2
@MoustafaAAtta Fred는이 게시물에 대한 답변입니까 : stackoverflow.com/questions/10715965/… 이 관점에서 더 좋습니까?
MysteryGuy

@MoustafaAAtta 데이터 프레임에 행만 추가하면 새 개체가 생성되지만 작은 데이터 집합의 경우 유용 할 수 있습니다. pandas.pydata.org/pandas-docs/stable/user_guide/…
geekidharsh

135

DataFrame을 만드는 올바른 방법

TLDR; (굵은 글씨를 읽으십시오)

여기에있는 대부분의 답변은 빈 DataFrame을 만들고 채우는 방법을 알려주지 만 나쁜 일이라고 말하는 사람은 없습니다.

여기 내 조언이 있습니다 : 작업 할 데이터가 모두 준비 될 때까지 기다리십시오. 목록을 사용하여 데이터를 수집 한 다음 준비가되면 DataFrame을 초기화하십시오.

data = []
for a, b, c in some_function_that_yields_data():
    data.append([a, b, c])

df = pd.DataFrame(data, columns=['A', 'B', 'C'])

빈 DataFrame (또는 NaN 중 하나)을 만들고 반복해서 추가하는 것보다 목록에 추가하고 한 번에 DataFrame을 만드는 것이 항상 저렴 합니다. 또한 목록은 메모리를 덜 차지하며 작업하기에 훨씬 가벼운 데이터 구조입니다. , 추가 및 제거 (필요한 경우)에 입니다.

이 방법의 다른 장점은 할당하는 대신 dtypes자동으로 유추됩니다object .

마지막 장점은 데이터에 대해 a RangeIndex가 자동으로 생성 되므로 걱정할 필요가 없다는 것입니다 (아래 의 가난한 방법 appendloc방법을 살펴보면 인덱스를 적절하게 처리 해야하는 요소가 모두 표시됩니다).


하지 말아야 할 것들

append또는 concat루프 내부

초보자에게서 본 가장 큰 실수는 다음과 같습니다.

df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
    # or similarly,
    # df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)

모든 작업 append또는 concat작업에 대해 메모리가 다시 할당됩니다 . 이것을 루프와 결합하면 2 차 복잡도 연산이 됩니다. 로부터 df.append문서 페이지 :

반복적으로 DataFrame에 행을 추가하면 단일 연결보다 계산 집약적 일 수 있습니다. 더 나은 해결책은 해당 행을 목록에 추가 한 다음 목록을 원래 DataFrame과 한 번에 연결하는 것입니다.

또 다른 실수 df.append는 사용자 가 추가 기능 을 잊어 버리는 경향이 있다는 점 입니다. 결과는 내부 기능 이 아니므로 결과를 다시 할당해야합니다. 또한 dtype에 대해 걱정해야합니다.

df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)

df.dtypes
A     object   # yuck!
B    float64
C     object
dtype: object

팬더는 해당 열에 대한 연산을 벡터화 할 수 없으므로 객체 열을 다루는 것은 결코 좋은 일이 아닙니다. 수정하려면 다음을 수행해야합니다.

df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object

loc 루프 내부

또한 loc비어있는 DataFrame에 추가하는 데 사용되는 것을 보았습니다 .

df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df.loc[len(df)] = [a, b, c]

이전과 같이 매번 필요한 메모리 양을 미리 할당하지 않았으므로 새 행을 만들 때마다 메모리가 다시 증가합니다 . 그것은만큼 나쁘다append 더 추악합니다.

NaN의 빈 데이터 프레임

그리고 NaN의 DataFrame과 이와 관련된 모든 경고가 생성됩니다.

df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
     A    B    C
0  NaN  NaN  NaN
1  NaN  NaN  NaN
2  NaN  NaN  NaN
3  NaN  NaN  NaN
4  NaN  NaN  NaN

다른 것과 같이 객체 열의 DataFrame을 만듭니다.

df.dtypes
A    object  # you DON'T want this
B    object
C    object
dtype: object

Appending은 여전히 ​​위의 방법으로 모든 문제가 있습니다.

for i, (a, b, c) in enumerate(some_function_that_yields_data()):
    df.iloc[i] = [a, b, c]

증명은 푸딩에 있습니다.

이러한 방법의 타이밍은 메모리와 유틸리티 측면에서 얼마나 다른지 확인할 수있는 가장 빠른 방법입니다.

여기에 이미지 설명을 입력하십시오

참조를위한 벤치마킹 코드.


6
이러한 유형의 질문에 가장 적합한 방법은 목록 추가입니다.
YOBEN_S 2016.

9
이것은 백만 배 이상 상향 조정되어야합니다. 데이터 프레임을 늘리지 마십시오!
Buggy

3
@ user3293236 오래된 질문에 대답 할 때마다 맨 아래부터 시작해야합니다.)
cs95

2
이것이 내가 가장 싫어하는 것 중 하나입니다. 몇 번이나 당신은 vote 𝒄𝒐𝒓𝒓𝒆𝒄𝒕 𝒂𝒏𝒔𝒘𝒆𝒓를 보았습니다. 빈 팬더 데이터 프레임을 만들려면 𝚍𝚏 = 𝚙𝚍.𝙳𝚊𝚝𝚊𝙵𝚛𝚊𝚖𝚎 ([]) 코드가 누락되었습니다. 이 답변을지지합니다. 훌륭한 설명, @ cs95!
jonathan

1
이것은 말 그대로 설명서에 있습니다. "DataFrame에 반복적으로 행을 추가하는 것은 단일 연결보다 계산 집약적 일 수 있습니다. 더 나은 해결책은 해당 행을 목록에 추가 한 다음 목록을 원래 DataFrame과 한 번에 연결하는 것입니다." pandas.pydata.org/pandas-docs/version/0.21/generated/…
endolith

132

열 이름으로 빈 프레임을 초기화하십시오.

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

프레임에 새 레코드 추가

my_df.loc[len(my_df)] = [2, 4, 5]

사전을 전달할 수도 있습니다.

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 

기존 프레임에 다른 프레임 추가

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

성능 고려 사항

루프 내부에 행을 추가하는 경우 성능 문제를 고려하십시오. 처음 1000 개 레코드의 경우 "my_df.loc"성능이 향상되지만 루프의 레코드 수를 늘림으로써 점차 느려집니다.

큰 루프 (10M 레코드 등) 안에서 씬을 만들 계획이라면이 두 가지를 혼합하여 사용하는 것이 좋습니다. 크기가 약 1000이 될 때까지 데이터 프레임을 iloc으로 채운 다음 원래 데이터 프레임에 추가하고 임시 데이터 프레임을 비 웁니다. 이렇게하면 성능이 약 10 배 향상됩니다.


my_df = my_df.append(my_df2)내가 지정하지 않으면 나를 위해 작동하지 않습니다 ignore_index=True.
Nasif Imtiaz Ohi

0

19 개의 행이있는 데이터 프레임을 가정

index=range(0,19)
index

columns=['A']
test = pd.DataFrame(index=index, columns=columns)

A 열을 일정하게 유지

test['A']=10

열 b를 루프가 제공하는 변수로 유지

for x in range(0,19):
    test.loc[[x], 'b'] = pd.Series([x], index = [x])

첫 x pd.Series([x], index = [x])를 임의의 값으로 바꿀 수 있습니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.