9

여러 개의 열이있는 팬더 데이터 프레임이 있습니다. 나는 행의 값에서 새 열 weighted_sumweight팬더에서 한 행의 모든 ​​요소에 대해 가중치를 계산하는 방법은 무엇입니까?

weighted_sum는 다음 값이 있어야 다른 열 벡터 dataframe 만들려면 : 나는 기능 sum(axis=1)을 발견

row[weighted_sum] = row[col0]*weight[0] + row[col1]*weight[1] + row[col2]*weight[2] + ...

을하지만, '아무튼 나를 weight으로 번식시키지 마십시오.

편집 : 조금 바뀌 었습니다.

weight은 다음과 같습니다

 0 
col1 0.5 
col2 0.3 
col3 0.2 

df은 다음과 같습니다

col1 col2 col3 
1.0 2.2 3.5 
6.1 0.4 1.2 

df*weightNan 값 가득 dataframe를 반환합니다. 가중치를 가정

+0

'DataFrame'과 '가중치'중 일부를 표시 할 수 있습니까? 왜 이렇게하는 데 문제가 있는지 명확하지 않습니다. 'weights'를 가지고 행 값의 내적을 원한다면'ndarray.dot' 메쏘드'row.values.dot (weights.values)'를 사용하십시오. –

답변

9

문제는 다른 크기의 프레임이있는 프레임에 다른 행 인덱스를 곱한 것입니다.

In [121]: df = DataFrame([[1,2.2,3.5],[6.1,0.4,1.2]], columns=list('abc')) 

In [122]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0)) 

In [123]: df 
Out[123]: 
      a   b   c 
0  1.00  2.20  3.50 
1  6.10  0.40  1.20 

In [124]: weight 
Out[124]: 
      0 
a  0.50 
b  0.30 
c  0.20 

In [125]: df * weight 
Out[125]: 
      0   a   b   c 
0  nan  nan  nan  nan 
1  nan  nan  nan  nan 
a  nan  nan  nan  nan 
b  nan  nan  nan  nan 
c  nan  nan  nan  nan 

당신은 칼럼에 액세스 할 수 있습니다 :

In [126]: df * weight[0] 
Out[126]: 
      a   b   c 
0  0.50  0.66  0.70 
1  3.05  0.12  0.24 

In [128]: (df * weight[0]).sum(1) 
Out[128]: 
0   1.86 
1   3.41 
dtype: float64 

을 또는 다른 DataFrame

In [127]: df.dot(weight) 
Out[127]: 
      0 
0  1.86 
1  3.41 

모두 함께 가져 오려면 다시 얻을 dot를 사용

In [130]: df['weighted_sum'] = df.dot(weight) 

In [131]: df 
Out[131]: 
      a   b   c weighted_sum 
0  1.00  2.20  3.50   1.86 
1  6.10  0.40  1.20   3.41 
여기에 솔루션입니다

다음은 각 방법의 timeit입니다. 큰 숫자는 DataFrame입니다. 넓은 DataFrame를 들어

In [145]: df = DataFrame(randn(10000000, 3), columns=list('abc')) 
weight 
In [146]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0)) 

In [147]: timeit df.dot(weight) 
10 loops, best of 3: 57.5 ms per loop 

In [148]: timeit (df * weight[0]).sum(1) 
10 loops, best of 3: 125 ms per loop 

:

In [162]: df = DataFrame(randn(10000, 1000)) 

In [163]: weight = DataFrame(randn(1000, 1)) 

In [164]: timeit df.dot(weight) 
100 loops, best of 3: 5.14 ms per loop 

In [165]: timeit (df * weight[0]).sum(1) 
10 loops, best of 3: 41.8 ms per loop 

그래서, dot보다 빠르고 읽을 수 있습니다.

참고 : 데이터 중 NaN의를 포함 할 경우는 당신은 곱셈 - 및 - 합계 방법을 사용한다 dot을 사용할 수 없습니다. dotnumpy.dot() (약 NaN을 처리하지 않음) 주위의 단순한 래퍼이므로 NaN을 처리 할 수 ​​없습니다.

+0

나는이 속도 향상에 상당히 놀랐지 만 실제로 그 점이 같은 결과를 가져올 지 확신하지 못합니다. 그리고'df.mul (weight) .sum (1)'은 거의 같다 (조금 느린 경우). –

+0

'df.dot (weight)'는'df'와'weight'가 모두'DataFrames'이고,'Series'는'Series'이고 둘 모두가'Series' 인 경우 스칼라 인'DataFrame'을 생성합니다. 숫자 적으로는 동등합니다. –

+0

속도 향상은 아마도'*'연산에 의해 생성 된 일시적인 것 때문일 것입니다. 'dot'는 그런 임시적인 것을 필요로하지 않습니다. –

6

방금 ​​곱셈 수와 합을 각 열에 대한 가중치의 시리즈입니다 :

In [11]: df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c']) 

In [12]: weights = pd.Series([7, 8, 9], index=['a', 'b', 'c']) 

In [13]: (df * weights) 
Out[13]: 
    a b c 
0 7 16 27 
1 28 40 54 

In [14]: (df * weights).sum(1) 
Out[14]: 
0  50 
1 122 
dtype: int64 

이 방법의 장점은 당신이 무게를하지 않으려는 열을 담당한다 :

In [21]: weights = pd.Series([7, 8], index=['a', 'b']) 

In [22]: (df * weights) 
Out[22]: 
    a b c 
0 7 16 NaN 
1 28 40 NaN 

In [23]: (df * weights).sum(1) 
Out[23]: 
0 23 
1 68 
dtype: float64