[python] 재현 가능한 팬더 예를 만드는 방법
적절한 시간을 보냈다 아르 자형 과 팬더그래서 태그에 pandas
질문이 재현 가능한 데이터를 포함하지 않을 가능성이 높습니다. 이는 R 커뮤니티 장려에 대해 꽤 잘되었다는 것을, 그리고 같은 가이드 덕분에 이 , 이민자 함께이 예제를 퍼팅에 대한 몇 가지 도움을받을 수 있습니다. 이 안내서를 읽고 재현 가능한 데이터를 다시 얻을 수있는 사람들은 종종 질문에 대한 답변을 얻는 것이 훨씬 더 좋습니다.
pandas
질문 에 대한 좋은 재현 가능한 예를 어떻게 만들 수 있습니까? 다음과 같은 간단한 데이터 프레임을 구성 할 수 있습니다.
import pandas as pd
df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice'],
'income': [40000, 50000, 42000]})
그러나 많은 예제 데이터 세트는보다 복잡한 구조가 필요합니다. 예 :
datetime
지수 또는 데이터- 여러 범주 형 변수 (
expand.grid()
주어진 변수의 모든 가능한 조합을 생성 하는 R의 함수 와 동등한가 ?) - 다중 인덱스 또는 패널 데이터
몇 줄의 코드를 사용하여 조롱하기 어려운 데이터 세트의 경우 데이터 dput()
구조를 재생성하기 위해 복사하여 붙여 넣을 수있는 코드를 생성 할 수있는 R 과 동등한가?
답변
참고 : 여기의 아이디어는 실제로 스택 오버플로에 대한 일반적인 질문 입니다.
면책 조항 : 좋은 질문을 작성하는 것은 어렵습니다.
좋은 점 :
-
실행 가능한 코드로 작은 * 예제 DataFrame을 포함하십시오.
In [1]: df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])
또는을 사용하여 “복사하여 붙여 넣기”
pd.read_clipboard(sep='\s\s+')
할 수 있도록하려면 스택 오버플로 강조 표시의 텍스트 서식을 지정하고 Ctrl+ K(또는 각 줄에 4 개의 공백을 추가)를 사용하거나 코드를 들여 쓰지 않고 코드 위아래에 3 개의 물결표를 배치 할 수 있습니다.In [2]: df Out[2]: A B 0 1 2 1 1 3 2 4 6
pd.read_clipboard(sep='\s\s+')
자신을 테스트 하십시오.* 정말 뜻 작은이 , 예를 들어 DataFrames의 대부분이 될 수보다 적은 6 행은 표창장은 필요로 하고, 나는 5 행에 그것을 할 수 내기.
df = df.head()
당신이 직면하고있는 문제를 나타내는 작은 DataFrame을 구성 할 수 있는지 확인하기 위해 주위를 둘러 보지 않으면으로 오류를 재현 할 수 있습니까?* 모든 규칙에는 예외가 있습니다. 명백한 규칙은 성능 문제 ( 이 경우 확실히 % timeit 및 % prun 사용 )에서 생성해야합니다 (np.random.seed를 사용하여 동일한 프레임을 갖도록 고려)
df = pd.DataFrame(np.random.randn(100000000, 10))
. “이 코드를 빨리 작성하십시오”는 사이트의 주제에 국한되지 않습니다 … -
원하는 결과를 작성하십시오 (위와 유사)
In [3]: iwantthis Out[3]: A B 0 1 5 1 4 6
숫자가 무엇인지 설명하십시오. 5는 A가 1 인 행에 대한 B 열의 합입니다.
-
시도한 코드 를 표시 하십시오 .
In [4]: df.groupby('A').sum() Out[4]: B A 1 5 4 6
그러나 잘못된 점을 말하십시오. A 열은 열이 아니라 인덱스에 있습니다.
-
당신이 한 몇 가지 조사 (보여 않는 워드 프로세서를 검색 , StackOverflow의 검색을 ), 요약을 제공합니다 :
합계에 대한 docstring은 단순히 “그룹 값의 합계 계산”을 나타냅니다.
GROUPBY 워드 프로세서는 이것에 대한 예제를 제공하지 않습니다.
따로 : 여기에 대한 답변은를 사용하는 것
df.groupby('A', as_index=False).sum()
입니다. -
타임 스탬프 열이있는 것과 관련이있는 경우 (예 : 리샘플링 등) 명시 적이며
pd.to_datetime
이를 위해 적용하십시오 **.df['date'] = pd.to_datetime(df['date']) # this column ought to be date..
** 때때로 이것은 문제 자체입니다 : 그것들은 문자열이었습니다.
나쁜 것 :
-
복사하여 붙여 넣을 수없는 MultiIndex를 포함하지 마십시오 (위 참조). 이것은 팬더 기본 표시에 대한 불만이지만 그럼에도 불구하고 성가시다.
In [11]: df Out[11]: C A B 1 2 3 2 6
올바른 방법은
set_index
호출 과 함께 일반 DataFrame을 포함시키는 것입니다 .In [12]: df = pd.DataFrame([[1, 2, 3], [1, 2, 6]], columns=['A', 'B', 'C']).set_index(['A', 'B']) In [13]: df Out[13]: C A B 1 2 3 2 6
-
원하는 결과를 줄 때 그 내용에 대한 통찰력을 제공하십시오.
B A 1 1 5 0
숫자를 어떻게 얻었는지에 대해 구체적으로 설명하십시오.
-
코드에 오류가 발생하면 전체 스택 추적을 포함하십시오 (너무 시끄 럽면 나중에 편집 할 수 있음). 줄 번호와 코드의 해당 줄을 표시하십시오.
못난이:
-
우리가 액세스 할 수없는 CSV에 연결하지 마십시오 (이상적으로 외부 소스에 연결하지 마십시오 …)
df = pd.read_csv('my_secret_file.csv') # ideally with lots of parsing options
대부분의 데이터는 우리가 얻는 독점적 입니다. 비슷한 데이터를 구성하고 문제를 재현 할 수 있는지 확인하십시오 (작은 것).
-
“큰”DataFrame이있는 것처럼 상황을 모호하게 설명하지 말고 전달할 때 일부 열 이름을 언급하십시오 (dtype은 언급하지 마십시오). 실제 상황을 보지 않고 완전히 무의미한 것에 대해 많은 세부 사항을 시도하십시오. 아마도이 단락의 끝까지 아무도 읽지 않을 것입니다.
에세이는 나쁩니다. 작은 예에서는 더 쉽습니다.
-
실제 질문에 도달하기 전에 10+ (100+ ??) 줄의 데이터를 포함시키지 마십시오.
우리는 우리의 일상 생활에서 이것을 충분히 볼 수 있습니다. 우리는하지만, 도움말을 원하는 하지 이런 … .
소개를 잘라 내고 문제를 일으키는 단계에서 관련 DataFrame (또는 작은 버전)을 표시하십시오.
어쨌든 Python, NumPy 및 Pandas를 배우는 재미가 있습니다!
답변
샘플 데이터 세트를 생성하는 방법
이것은 주로 샘플 데이터 프레임을 만드는 방법에 대한 예제를 제공하여 @AndyHayden의 답변을 확장하는 것입니다. 팬더 및 (특히) numpy는 몇 줄의 코드로 일반적으로 실제 데이터 세트의 합리적인 팩시밀리를 만들 수 있도록 다양한 도구를 제공합니다.
숫자와 팬더를 가져온 후 사람들이 데이터와 결과를 정확하게 재현 할 수있게하려면 임의의 시드를 제공해야합니다.
import numpy as np
import pandas as pd
np.random.seed(123)
부엌 싱크대 예
다음은 수행 할 수있는 다양한 작업을 보여주는 예입니다. 모든 종류의 유용한 샘플 데이터 프레임은 다음과 같은 하위 집합으로 만들 수 있습니다.
df = pd.DataFrame({
# some ways to create random data
'a':np.random.randn(6),
'b':np.random.choice( [5,7,np.nan], 6),
'c':np.random.choice( ['panda','python','shark'], 6),
# some ways to create systematic groups for indexing or groupby
# this is similar to r's expand.grid(), see note 2 below
'd':np.repeat( range(3), 2 ),
'e':np.tile( range(2), 3 ),
# a date range and set of random dates
'f':pd.date_range('1/1/2011', periods=6, freq='D'),
'g':np.random.choice( pd.date_range('1/1/2011', periods=365,
freq='D'), 6, replace=False)
})
이것은 다음을 생성합니다.
a b c d e f g
0 -1.085631 NaN panda 0 0 2011-01-01 2011-08-12
1 0.997345 7 shark 0 1 2011-01-02 2011-11-10
2 0.282978 5 panda 1 0 2011-01-03 2011-10-30
3 -1.506295 7 python 1 1 2011-01-04 2011-09-07
4 -0.578600 NaN shark 2 0 2011-01-05 2011-02-27
5 1.651437 7 python 2 1 2011-01-06 2011-02-03
몇 가지 참고 사항 :
np.repeat
및np.tile
(열d
및e
)은 매우 일반적인 방법으로 그룹과 인덱스를 만드는 데 매우 유용합니다. 2 열의 경우 r을 쉽게 복제하는 데 사용할 수expand.grid()
있지만 모든 순열의 하위 집합을 제공하는 기능이 더 유연합니다. 그러나 3 개 이상의 열의 경우 구문이 까다로워집니다.- 연구의의를위한보다 직접적인 교환에 대해서는
expand.grid()
투시itertools
의 솔루션 팬더가 요리 책 이나np.meshgrid
솔루션이 표시 여기 . 그것들은 여러 차원을 허용합니다. - 로 꽤 많은 일을 할 수 있습니다
np.random.choice
. 예를 들어 란g
에 2011 년부터 6 개의 날짜를 무작위로 선택했습니다. 또한replace=False
이 날짜를 고유하게 설정할 수 있습니다.이 값을 고유 한 값을 가진 인덱스로 사용하려는 경우 매우 유용합니다.
가짜 주식 시장 데이터
위 코드의 하위 집합을 가져 오는 것 외에도 기술을 결합하여 거의 모든 작업을 수행 할 수 있습니다. 예를 들어, 다음 은 동일한 날짜를 포함하는 4 개의 주식에 대한 샘플 티커 데이터를 결합 np.tile
하고 date_range
생성 하는 간단한 예입니다 .
stocks = pd.DataFrame({
'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
'price':(np.random.randn(100).cumsum() + 10) })
이제 100 줄 (티커 당 25 날짜)의 샘플 데이터 세트가 있지만 4 줄만 사용하여 100 줄의 코드를 복사하여 붙여 넣지 않고도 누구나 쉽게 재생할 수 있습니다. 그런 다음 질문을 설명하는 데 도움이되는 경우 데이터의 하위 집합을 표시 할 수 있습니다.
>>> stocks.head(5)
date price ticker
0 2011-01-01 9.497412 aapl
1 2011-01-02 10.261908 aapl
2 2011-01-03 9.438538 aapl
3 2011-01-04 9.515958 aapl
4 2011-01-05 7.554070 aapl
>>> stocks.groupby('ticker').head(2)
date price ticker
0 2011-01-01 9.497412 aapl
1 2011-01-02 10.261908 aapl
25 2011-01-01 8.277772 goog
26 2011-01-02 7.714916 goog
50 2011-01-01 5.613023 yhoo
51 2011-01-02 6.397686 yhoo
75 2011-01-01 11.736584 msft
76 2011-01-02 11.944519 msft
답변
답변자 일기
질문을 할 때 가장 좋은 조언은 질문에 대답하는 사람들의 심리학을 다루는 것입니다. 나는 그 사람들 중 하나이기 때문에 왜 특정 질문에 대답하고 왜 다른 질문에 대답하지 않는지 통찰력을 줄 수 있습니다.
동기 부여
여러 가지 이유로 질문에 대답하려고합니다.
- Stackoverflow.com은 저에게 매우 귀중한 자료였습니다. 포기하고 싶었다.
- 환원하려는 노력으로이 사이트가 이전보다 훨씬 더 강력한 리소스라는 것을 알게되었습니다. 질문에 대답하는 것은 저에게는 학습 경험이며 배우고 싶습니다. 이 답변을 읽고 다른 수의사로부터 의견을 주십시오. 이런 종류의 상호 작용은 나를 행복하게 만듭니다.
- 나는 포인트를 좋아한다!
- # 3을 참조하십시오.
- 나는 흥미로운 문제를 좋아한다.
나의 가장 순수한 의도는 모두 위대하고 모든 것이지만, 한 질문 또는 30 개의 질문에 대답하면 그 만족도를 얻습니다. 어떤 질문에 대답 할 수있는 선택 을 이끌어 내는가 포인트 극대화의 큰 요소를 가지고 있습니다.
나는 또한 흥미로운 문제에 시간을 할애하지만 그 사이에는별로 없으며 관심이없는 질문에 대한 해결책이 필요한 질문을하는 사람에게는 도움이되지 않습니다. 내가 질문에 대답하게하는 최선의 방법은 가능한 적은 노력으로 그 질문에 답할 수 있도록 잘 익은 플래터에 그 질문을 제공하는 것입니다. 두 가지 질문을보고 있고 하나는 코드가있는 경우 붙여 넣기를 복사하여 필요한 모든 변수를 만들 수 있습니다 … 그중 하나를 취하고 있습니다! 시간이 있으면 다른 곳으로 다시 올게요
주요 조언
사람들이 질문에 쉽게 대답 할 수 있도록하십시오.
- 필요한 변수를 작성하는 코드를 제공하십시오.
- 해당 코드를 최소화하십시오. 게시물을 보면서 눈이 번쩍이면 다음 질문으로 넘어가거나 다른 일을하고 있습니다.
- 당신이 요구하는 것을 생각하고 구체적으로 생각하십시오. 자연어 (영어)가 부정확하고 혼동되기 때문에 수행 한 작업을 확인하려고합니다. 시도한 코드 샘플은 자연어 설명에서 불일치를 해결하는 데 도움이됩니다.
- 기대하는 것을 보여주세요 !!! 나는 앉아서 일을해야합니다. 나는 어떤 일을 시도하지 않고 질문에 대한 답을 거의 알지 못합니다. 당신이 찾고있는 것의 예를 볼 수 없다면, 나는 추측하고 싶지 않기 때문에 질문을 전달할 수 있습니다.
당신의 명성은 단순한 명성 이상의 것입니다.
나는 포인트를 좋아한다 (위에 언급했다). 그러나 그 점은 실제로 내 명성이 아닙니다. 내 진정한 평판은 사이트의 다른 사람들이 나를 어떻게 생각하는지에 대한 융합입니다. 나는 공정하고 정직하기 위해 노력하며 다른 사람들이 그것을 볼 수 있기를 바랍니다. 그 질문의 의미는, 우리는 요청자의 행동을 기억합니다. 답을 선택하지 않고 정답을 찬성하면 기억합니다. 내가 좋아하지 않거나 좋아하는 방식으로 행동하면 기억합니다. 이것은 또한 내가 어떤 질문에 대답 할 것인지에 달려 있습니다.
어쨌든, 아마도 갈 수는 있지만 실제로 이것을 읽는 당신을 모두 구할 것입니다.
답변
과제 SO 질문에 응답하는 데있어 가장 어려운 측면 중 하나는 문제를 재현하는 데 걸리는 시간 (데이터 포함)입니다. 데이터를 명확하게 재현 할 수없는 질문에 대한 답변이 적습니다. 질문을 작성하는 데 시간이 걸리고 도움이 필요한 문제가있는 경우 다른 사람이 문제를 해결하는 데 사용할 수있는 데이터를 제공하여 쉽게 도움을 줄 수 있습니다.
좋은 팬더 질문을 작성하기 위해 @Andy가 제공하는 지침은 시작하기에 좋은 장소입니다. 자세한 정보 는 요청 방법 및 최소, 완료 및 검증 가능한 예제 작성 방법을 참조하십시오 .
질문을 명확하게 진술하십시오. 질문과 샘플 코드를 작성하는 데 시간이 걸리면 질문을 읽고 독자에게 문제를 요약하고 명확하게 설명하는 ‘실행 요약’을 제공하십시오.
원래 질문 :
이 데이터가 있습니다 …
나는 이것을하고 싶다 …
내 결과가 다음과 같이 보이기를 원합니다 …
그러나 [this]를 시도하면 다음과 같은 문제가 발생합니다.
나는 [this]와 [that]을함으로써 해결책을 찾으려고 노력했다.
어떻게 고치나요?
제공된 데이터 양, 샘플 코드 및 오류 스택에 따라 독자는 문제가 무엇인지 이해하기 전에 먼 길을 가야합니다. 질문 자체가 맨 위에 오도록 질문을 정리 한 다음 필요한 세부 사항을 제공하십시오.
수정 된 질문 :
인용 : 어떻게해야합니까?
나는 [this]와 [that]을함으로써 해결책을 찾으려고 노력했다.
[이것]을 시도하면 다음과 같은 문제가 발생합니다.
최종 결과는 다음과 같습니다.
내 문제를 재현 할 수있는 최소한의 코드가 있습니다 …
다음은 샘플 데이터를 재생성하는 방법입니다.
df = pd.DataFrame({'A': [...], 'B': [...], ...})
필요한 경우 샘플 데이터 제공 !!!
때로는 DataFrame의 머리 또는 꼬리 만 있으면됩니다. @JohnE에서 제안한 방법을 사용하여 다른 사람이 재생할 수있는 더 큰 데이터 집합을 만들 수도 있습니다. 그의 예제를 사용하여 주가의 100 행 DataFrame을 생성합니다.
stocks = pd.DataFrame({
'ticker':np.repeat( ['aapl','goog','yhoo','msft'], 25 ),
'date':np.tile( pd.date_range('1/1/2011', periods=25, freq='D'), 4 ),
'price':(np.random.randn(100).cumsum() + 10) })
이것이 실제 데이터 인 경우 다음과 같이 데이터 프레임의 머리 및 / 또는 꼬리를 포함시킬 수 있습니다 (민감한 데이터를 익명화해야 함).
>>> stocks.head(5).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
1: Timestamp('2011-01-01 00:00:00'),
2: Timestamp('2011-01-01 00:00:00'),
3: Timestamp('2011-01-01 00:00:00'),
4: Timestamp('2011-01-02 00:00:00')},
'price': {0: 10.284260107718254,
1: 11.930300761831457,
2: 10.93741046217319,
3: 10.884574289565609,
4: 11.78005850418319},
'ticker': {0: 'aapl', 1: 'aapl', 2: 'aapl', 3: 'aapl', 4: 'aapl'}}
>>> pd.concat([stocks.head(), stocks.tail()], ignore_index=True).to_dict()
{'date': {0: Timestamp('2011-01-01 00:00:00'),
1: Timestamp('2011-01-01 00:00:00'),
2: Timestamp('2011-01-01 00:00:00'),
3: Timestamp('2011-01-01 00:00:00'),
4: Timestamp('2011-01-02 00:00:00'),
5: Timestamp('2011-01-24 00:00:00'),
6: Timestamp('2011-01-25 00:00:00'),
7: Timestamp('2011-01-25 00:00:00'),
8: Timestamp('2011-01-25 00:00:00'),
9: Timestamp('2011-01-25 00:00:00')},
'price': {0: 10.284260107718254,
1: 11.930300761831457,
2: 10.93741046217319,
3: 10.884574289565609,
4: 11.78005850418319,
5: 10.017209045035006,
6: 10.57090128181566,
7: 11.442792747870204,
8: 11.592953372130493,
9: 12.864146419530938},
'ticker': {0: 'aapl',
1: 'aapl',
2: 'aapl',
3: 'aapl',
4: 'aapl',
5: 'msft',
6: 'msft',
7: 'msft',
8: 'msft',
9: 'msft'}}
관련 열만 사용하여 DataFrame에 대한 설명을 제공 할 수도 있습니다. 이를 통해 다른 사람들이 각 열의 데이터 유형을 확인하고 다른 일반적인 오류 (예 : 날짜를 문자열 대 날짜 / 시간 64 대 개체)를 식별 할 수 있습니다.
stocks.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 100 entries, 0 to 99
Data columns (total 3 columns):
date 100 non-null datetime64[ns]
price 100 non-null float64
ticker 100 non-null object
dtypes: datetime64[ns](1), float64(1), object(1)
참고 : DataFrame에 다중 인덱스가있는 경우 :
DataFrame에 다중 색인이있는 경우을 호출하기 전에 먼저 재설정해야합니다 to_dict
. 그런 다음 다음을 사용하여 색인을 다시 작성해야합니다 set_index
.
# MultiIndex example. First create a MultiIndex DataFrame.
df = stocks.set_index(['date', 'ticker'])
>>> df
price
date ticker
2011-01-01 aapl 10.284260
aapl 11.930301
aapl 10.937410
aapl 10.884574
2011-01-02 aapl 11.780059
...
# After resetting the index and passing the DataFrame to `to_dict`, make sure to use
# `set_index` to restore the original MultiIndex. This DataFrame can then be restored.
d = df.reset_index().to_dict()
df_new = pd.DataFrame(d).set_index(['date', 'ticker'])
>>> df_new.head()
price
date ticker
2011-01-01 aapl 10.284260
aapl 11.930301
aapl 10.937410
aapl 10.884574
2011-01-02 aapl 11.780059
답변
다음은 dput
Pandas DataFrame
의 재현 가능한 보고서를 생성하는 표준 R 도구 의 내 버전입니다 . 더 복잡한 프레임에서는 실패 할 수 있지만 간단한 경우에는 작업을 수행하는 것 같습니다.
import pandas as pd
def dput (x):
if isinstance(x,pd.Series):
return "pd.Series(%s,dtype='%s',index=pd.%s)" % (list(x),x.dtype,x.index)
if isinstance(x,pd.DataFrame):
return "pd.DataFrame({" + ", ".join([
"'%s': %s" % (c,dput(x[c])) for c in x.columns]) + (
"}, index=pd.%s)" % (x.index))
raise NotImplementedError("dput",type(x),x)
지금,
df = pd.DataFrame({'a':[1,2,3,4,2,1,3,1]})
assert df.equals(eval(dput(df)))
du = pd.get_dummies(df.a,"foo")
assert du.equals(eval(dput(du)))
di = df
di.index = list('abcdefgh')
assert di.equals(eval(dput(di)))
참고 이보다 훨씬 더 자세한 출력을 생성하는 것을 DataFrame.to_dict
예를,
pd.DataFrame({ 'foo_1':pd.Series([1, 0, 0, 0, 0, 1, 0, 1],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)), 'foo_2':pd.Series([0, 1, 0, 0, 1, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)), 'foo_3':pd.Series([0, 0, 1, 0, 0, 0, 1, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1)), 'foo_4':pd.Series([0, 0, 0, 1, 0, 0, 0, 0],dtype='uint8',index=pd.RangeIndex(start=0, stop=8, step=1))}, index=pd.RangeIndex(start=0, stop=8, step=1))
vs
{'foo_1': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 0, 7: 1}, 'foo_2': {0: 0, 1: 1, 2: 0, 3: 0, 4: 1, 5: 0, 6: 0, 7: 0}, 'foo_3': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0, 6: 1, 7: 0}, 'foo_4': {0: 0, 1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 6: 0, 7: 0}}
위해 du
위,하지만 열 유형을 유지 . 예를 들어, 위 테스트 사례에서
du.equals(pd.DataFrame(du.to_dict()))
==> False
때문에이 du.dtypes
있다 uint8
하고 pd.DataFrame(du.to_dict()).dtypes
있다 int64
.