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

나는 판다 데이터 프레임 문서에서 시작하고 있습니다 : 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



답변

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

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


답변

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

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 ()


답변

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]

증명은 푸딩에 있습니다.

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

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

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


답변

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

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 배 향상됩니다.


답변

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])를 임의의 값으로 바꿀 수 있습니다


답변