2014-07-14 53 views
2

我有一個熊貓系列這樣的:移動窗口分類值與熊貓

s = pd.Series(["A", "A", "B", "C", "A", "C", "A", "C", "A", "B", "B", "B", "A", "A", "C"]) 

我想有計數或大小的不相重疊的窗口每個字母的比例4.

我試過這個:

pd.rolling_apply(s, 4, pd.value_counts) 

但它不起作用。

ValueError: could not convert string to float: C 

任何想法來執行此任務?

回答

0

不錯的拼圖! 我使用for循環來獲取所有窗口的字典。然後我構建一個DataFrame,然後我可以使用value_counts()。這是你要求的嗎?

In [150]: winsize = 4 

In [151]: for i in range(len(s)+1-winsize): wd[i] = s[i:i+winsize].tolist() 

In [152]: wd 
Out[152]: 
{0: ['A', 'A', 'B', 'C'], 
1: ['A', 'B', 'C', 'A'], 
2: ['B', 'C', 'A', 'C'], 
3: ['C', 'A', 'C', 'A'], 
4: ['A', 'C', 'A', 'C'], 
5: ['C', 'A', 'C', 'A'], 
6: ['A', 'C', 'A', 'B'], 
7: ['C', 'A', 'B', 'B'], 
8: ['A', 'B', 'B', 'B'], 
9: ['B', 'B', 'B', 'A'], 
10: ['B', 'B', 'A', 'A'], 
11: ['B', 'A', 'A', 'C']} 

In [153]: pd.DataFrame(wd) 
Out[153]: 
    0 1 2 3 4 5 6 7 8 9 10 11 
0 A A B C A C A C A B B B 
1 A B C A C A C A B B B A 
2 B C A C A C A B B B A A 
3 C A C A C A B B B A A C 

In [154]: pd.DataFrame(wd).apply(pd.value_counts) 
Out[154]: 
    0 1 2 3 4 5 6 7 8 9 10 11 
A 2 2 1 2 2 2 2 1 1 1 2 2 
B 1 1 1 NaN NaN NaN 1 2 3 3 2 1 
C 1 1 2 2 2 2 1 1 NaN NaN NaN 1 
+0

謝謝,我會看看。我只是想要非重疊窗口,但這不是一個pb我想,你只需要在範圍內添加一個步驟。 – jrjc

1

由於您的系列採用了RangeIndex,你可以通過它們的大小將創建非重疊窗口:

print(s.index // 4) 
# => Int64Index([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3], dtype='int64') 

集團通過以上並使用.value_counts()

s.groupby(s.index // 4).value_counts() 

# 0 A 2 
# B 1 
# C 1 
# 1 A 2 
# C 2 
# 2 B 3 
# A 1 
# 3 A 2 
# C 1 
# dtype: int64 

如果您更喜歡比例而不是計數,請給出.value_counts()參數normalize=True

s.groupby(s.index // 4).value_counts(normalize=True) 

# 0 A 0.500000 
# B 0.250000 
# C 0.250000 
# 1 A 0.500000 
# C 0.500000 
# 2 B 0.750000 
# A 0.250000 
# 3 A 0.666667 
# C 0.333333 
# dtype: float64 

如果您的系列有不同的指標,你仍然可以生成Windows如下:

pd.Series(range(len(s))) // 4 

# 0  0 
# 1  0 
# 2  0 
# 3  0 
# 4  1 
# 5  1 
# 6  1 
# 7  1 
# 8  2 
# 9  2 
# 10 2 
# 11 2 
# 12 3 
# 13 3 
# 14 3 
# dtype: int64 

以下任何兩行導致相同的輸出上面:

s.groupby(pd.Series(range(len(s))) // 4).value_counts() 
s.groupby(pd.Series(range(len(s))) // 4).value_counts(normalize=True)