python - 합치기 - 파이썬 리스트 데이터프레임 변환




Python pandas의 기존 DataFrame에 새 열 추가 (14)

다음과 같은 명명 된 열과 행을 가진 다음과 같은 인덱싱 된 DataFrame이 있습니다.

          a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493

기존 데이터 프레임에 새 열 'e' 를 추가하고 데이터 프레임에서 아무 것도 변경하지 않으려합니다. 즉, 새 열의 길이는 항상 DataFrame과 같습니다.

0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64

내가 join 다른 버전을 시도, append , merge 하지만, 내가 원하는 결과를 얻지 못했습니다, 오직 오류. 위 예제에 열 e 를 어떻게 추가 할 수 있습니까?


기존의 데이터 프레임에 새로운 열 'e'를 추가하고 데이터 프레임에서 아무 것도 변경하지 않으려합니다. (이 시리즈는 항상 데이터 프레임과 길이가 같습니다.)

e 의 인덱스 값이 df1 의 인덱스 값과 일치한다고 가정합니다.

e 라는 새 열을 시작하고이 열에 일련의 값을 할당하는 가장 쉬운 방법은 다음과 같습니다. e :

df['e'] = e.values

할당 (팬더 0.16.0 이상)

Pandas 0.16.0에서 assign 을 사용하여 새 열을 DataFrame에 할당하고 새로운 열 (원래 열 모두)을 새 객체 (사본)로 반환 할 수 있습니다.

df1 = df1.assign(e=e.values)

이 예제 ( assign 함수의 소스 코드도 포함)에 따라 둘 이상의 열을 포함 할 수도 있습니다.

df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
   a  b  mean_a  mean_b
0  1  3     1.5     3.5
1  2  4     1.5     3.5

예제와 관련하여 :

np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))

>>> df1
          a         b         c         d
0  1.764052  0.400157  0.978738  2.240893
2 -0.103219  0.410599  0.144044  1.454274
3  0.761038  0.121675  0.443863  0.333674
7  1.532779  1.469359  0.154947  0.378163
9  1.230291  1.202380 -0.387327 -0.302303

>>> e
0   -1.048553
1   -1.420018
2   -1.706270
3    1.950775
4   -0.509652
dtype: float64

df1 = df1.assign(e=e.values)

>>> df1
          a         b         c         d         e
0  1.764052  0.400157  0.978738  2.240893 -1.048553
2 -0.103219  0.410599  0.144044  1.454274 -1.420018
3  0.761038  0.121675  0.443863  0.333674 -1.706270
7  1.532779  1.469359  0.154947  0.378163  1.950775
9  1.230291  1.202380 -0.387327 -0.302303 -0.509652

이 새로운 기능이 처음 소개되었을 때의 설명은 here 에서 찾을 수 here .


슈퍼 단순 열 지정

팬더 데이터 프레임은 순서가 지정된 열의 사전으로 구현됩니다.

즉, __getitem__ [] 는 특정 열을 가져올 수있을뿐만 아니라 __setitem__ [] = 을 사용하여 새 열을 할당 할 수 있습니다.

예를 들어,이 데이터 프레임은 [] 접근자를 사용하여 열을 추가 할 수 있습니다

    size      name color
0    big      rose   red
1  small    violet  blue
2  small     tulip   red
3  small  harebell  blue

df['protected'] = ['no', 'no', 'no', 'yes']

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

데이터 프레임의 인덱스가 꺼져 있어도이 방법이 작동합니다.

df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

[=]가는 방법이지만, 조심해!

그러나 pd.Series 있고 인덱스가없는 데이터 프레임에 할당하려고하면 문제가 생길 것입니다. 예제보기 :

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

pd.Series 에는 기본적으로 0에서 n까지 열거 된 인덱스가 있기 때문입니다. 그리고 pandas [] = method "똑똑한"

실제로 무슨 일이 일어나고 있는지.

[] = 메서드를 사용하면 pandas는 왼손 데이터 프레임의 인덱스와 오른쪽 시리즈의 인덱스를 사용하여 외부 조인 또는 외부 병합을 자동으로 수행합니다. df['column'] = series

사이드 노트

이것은 []= 메소드가 입력에 따라 다른 많은 일을하려고하기 때문에인지 부조화를 빠르게 일으키고, 팬더가 어떻게 작동하는지 알지 못하면 결과를 예측할 수 없습니다. 따라서 코드베이스에서 []= 에 대한 조언을하지만 노트북에서 데이터를 탐색 할 때는 괜찮습니다.

문제 해결하기

pd.Series 를 가지고 있고 그것을 위에서 아래로 할당하고자하거나, 생산적 코드를 코딩하고 있고 인덱스 순서가 확실하지 않은 경우에는 이런 종류의 문제를 방지하는 것이 좋습니다.

pd.Seriesnp.ndarray 또는 list 다운 캐스팅하면 트릭을 수행 할 수 있습니다.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values

또는

df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))

그러나 이것은 매우 명확하지 않습니다.

어떤 코더가 와서 "이봐, 이건 중복 된 것 같아. 나는 이걸 최적화 할거야."라고 말할지도 모릅니다.

명백한 방법

pd.Series 의 색인을 df 의 색인으로 설정하는 것은 명시 적입니다.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)

또는 더 현실적으로 pd.Series 이미 사용할 수 있습니다.

protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index

3     no
2     no
1     no
0    yes

이제 할당 될 수 있습니다.

df['protected'] = protected_series

    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

df.reset_index() 다른 방법

인덱스 불협화음이 문제이기 때문에 데이터 프레임의 인덱스가 일을 지시 해서는 안된다고 생각하면 간단히 인덱스를 삭제할 수 있습니다.이 속도는 빨라야하지만 함수는 이제 두 가지 일을하기 때문에 매우 깨끗하지는 않습니다.

df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

df.assign 에 대한 참고 사항

df.assign 은 당신이하는 일을 좀더 명확하게 해 df.assign 실제로는 위의 []=

df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

df.assign 을 사용하여 자신의 열이 self 가 아닌 것을주의하십시오. 오류가 발생할 것입니다. 이렇게하면 df.assign 냄새df.assign . 왜냐하면이 함수에 이러한 종류의 인공물이 있기 때문입니다.

df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'

당신은 "글쎄, 난 단지 self 를 사용하지 않을거야"라고 말할지도 모른다. 그러나 누가 새로운 기능을 지원하기 위해 미래에이 기능이 어떻게 변하는 지 알 수 있습니다. 어쩌면 열 이름이 판다의 새 업데이트에서 논의가 될 것이므로 업그레이드하는 데 문제가 발생할 수 있습니다.


가장 쉬운 방법 : -

데이터 [ 'new_col'] = 목록 _ 값

data.loc [:, 'new_col'] = list_of_values


그냥 처럼 .locSettingWithCopyWarning 해결하지 못했고 df.insert()df.insert() . 필자의 경우 위조 긍정은 " 'e' 가 새 열이고 dict['a'] 가 사전에서 오는 DataFrame 인 "fake"chain indexing dict['a']['e'] 의해 생성되었습니다.

또한 수행중인 작업을 알고있는 경우 pd.options.mode.chained_assignment = None 사용하여 경고를 전환하고 여기에 나와있는 다른 솔루션 중 하나를 사용하십시오.


나는 두려운 SettingWithCopyWarning 받았고 iloc 구문을 사용하여 해결되지 않았습니다. 내 DataFrame은 ODBC 원본의 read_sql에 의해 만들어졌습니다. 위의 lowtech의 제안을 사용하여 다음 작업이 저에게 효과적이었습니다.

df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength),  index=df.index))

이것은 끝에 열을 삽입하는 데는 효과가있었습니다. 가장 효율적인 지 모르겠지만 경고 메시지가 마음에 들지 않습니다. 나는 더 나은 해결책이 있다고 생각하지만, 그것을 발견 할 수 없다. 그리고 나는 그것이 인덱스의 어떤면에 달려 있다고 생각한다.
참고 . 이 작업은 한 번만 작동하며 기존 열을 덮어 쓰려고하면 오류 메시지가 표시됩니다.
참고 위와 0.16.0부터 할당은 최상의 솔루션입니다. http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign 문서를 참조하십시오. 중간 값을 덮어 쓰지 않는 데이터 흐름 유형에 적합합니다.


나는 바보 SettingWithCopyWarning 을 얻지 않고 데이터 프레임에 numpy.nan 의 열을 추가하는 일반적인 방법을 찾고 SettingWithCopyWarning .

다음으로부터 :

  • 대답은 여기에있다.
  • 변수를 키워드 인수로 전달하는 것에 관한 이 질문
  • 인라인으로 NaN의 numpy 배열을 생성하는 이 메소드

나는 이것을 생각해 냈다.

col = 'column_name'
df = df.assign(**{col:numpy.full(len(df), numpy.nan)})

데이터 프레임과 Series 객체가 동일한 인덱스 를 가지고 pandas.concat 도 여기에서 작동합니다.

import pandas as pd
df
#          a            b           c           d
#0  0.671399     0.101208   -0.181532    0.241273
#1  0.446172    -0.243316    0.051767    1.577318
#2  0.614758     0.075793   -0.451460   -0.012493

e = pd.Series([-0.335485, -1.166658, -0.385571])    
e
#0   -0.335485
#1   -1.166658
#2   -0.385571
#dtype: float64

# here we need to give the series object a name which converts to the new  column name 
# in the result
df = pd.concat([df, e.rename("e")], axis=1)
df

#          a            b           c           d           e
#0  0.671399     0.101208   -0.181532    0.241273   -0.335485
#1  0.446172    -0.243316    0.051767    1.577318   -1.166658
#2  0.614758     0.075793   -0.451460   -0.012493   -0.385571

동일한 색인이없는 경우 :

e.index = df.index
df = pd.concat([df, e.rename("e")], axis=1)

새 열을 할당하기 전에 데이터를 인덱싱 한 경우 인덱스를 정렬해야합니다. 적어도 내 경우에는 다음과 같이해야했다.

data.set_index(['index_column'], inplace=True)
"if index is unsorted, assignment of a new column will fail"        
data.sort_index(inplace = True)
data.loc['index_value1', 'column_y'] = np.random.randn(data.loc['index_value1', 'column_x'].shape[0])

원래 df1 색인을 사용하여 시리즈를 작성하십시오.

df1['e'] = Series(np.random.randn(sLength), index=df1.index)

2015 편집
어떤 사람들은이 코드로 SettingWithCopyWarningSettingWithCopyWarning 보고했습니다.
그러나 코드는 현재 팬더 버전 0.16.1에서 완벽하게 실행됩니다.

>>> sLength = len(df1['a'])
>>> df1
          a         b         c         d
6 -0.269221 -0.026476  0.997517  1.294385
8  0.917438  0.847941  0.034235 -0.448948

>>> df1['e'] = p.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e
6 -0.269221 -0.026476  0.997517  1.294385  1.757167
8  0.917438  0.847941  0.034235 -0.448948  2.228131

>>> p.version.short_version
'0.16.1'

SettingWithCopyWarning 은 Dataframe 복사본에서 잘못된 할당을 알리기위한 것입니다. 반드시 틀린 것은 아닙니다 (오탐 (false positive)을 유발할 수 있습니다.)하지만 0.13.0부터는 같은 목적을위한 적절한 방법이 더 있음을 알려줍니다. 그런 다음 경고 메시지가 표시되면 조언을 따르십시오. .loc [row_index, col_indexer] = value를 대신 사용해보십시오 .

>>> df1.loc[:,'f'] = p.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e         f
6 -0.269221 -0.026476  0.997517  1.294385  1.757167 -0.050927
8  0.917438  0.847941  0.034235 -0.448948  2.228131  0.006109
>>> 

실제로 이것은 현재 pandas docs에 설명 된 것처럼보다 효율적인 방법입니다.

2017 편집

주석과 @Alexander에 표시된 것처럼 현재 Series의 값을 DataFrame의 새 열로 추가하는 가장 좋은 방법은 assign 사용 assign .

df1 = df1.assign(e=p.Series(np.random.randn(sLength)).values)

이것은 새로운 열을 추가하는 간단한 방법입니다 : df['e'] = e


최근 팬더 버전에서 assign 을 사용하는 방법이 있습니다 :

df1 = df1.assign(e=np.random.randn(sLength))

SettingWithCopyWarning 생성하지 않습니다.


추가하려는 열이 계열 변수 인 경우 다음과 같이하면됩니다.

df["new_columns_name"]=series_variable_name #this will do it for you

이것은 기존 컬럼을 대체하더라도 잘 작동합니다. 교체하려는 컬럼과 동일한 new_columns_name 만 입력하십시오. 기존 컬럼 데이터를 새 시리즈 데이터로 겹쳐 쓰게됩니다.


NumPy 를 통해이 작업을 직접 수행하는 것이 가장 효율적입니다.

df1['e'] = np.random.randn(sLength)

원래 (아주 오래된) 제안은 map 을 사용하는 것이 었습니다 (훨씬 느림).

df1['e'] = df1['a'].map(lambda x: np.random.random())

SettingWithCopyWarning 경우, 쉽게 수정할 수있는 방법은 열을 추가하려는 DataFrame을 복사하는 것입니다.

df = df.copy()
df['col_name'] = values




chained-assignment