2016-08-03 87 views
12

鉴于从SFrame矩阵:有效的方式,从2列或多列获得唯一值的数据帧

>>> from sframe import SFrame 
>>> sf =SFrame({'x':[1,1,2,5,7], 'y':[2,4,6,8,2], 'z':[2,5,8,6,2]}) 
>>> sf 
Columns: 
    x int 
    y int 
    z int 

Rows: 5 

Data: 
+---+---+---+ 
| x | y | z | 
+---+---+---+ 
| 1 | 2 | 2 | 
| 1 | 4 | 5 | 
| 2 | 6 | 8 | 
| 5 | 8 | 6 | 
| 7 | 2 | 2 | 
+---+---+---+ 
[5 rows x 3 columns] 

我想要得到的唯一值的xy列,我能做到这一点因此:

>>> sf['x'].unique().append(sf['y'].unique()).unique() 
dtype: int 
Rows: 7 
[2, 8, 5, 4, 1, 7, 6] 

这样我就可以得到x的唯一值和y的唯一值,然后附加它们并获得附加列表的唯一值。

我也能做到这一点是这样的:

>>> sf['x'].append(sf['y']).unique() 
dtype: int 
Rows: 7 
[2, 8, 5, 4, 1, 7, 6] 

但这样一来,如果我的X和Y列是巨大的,有很多重复的,我将其追加到一个非常巨大的容器,得到独特的前。

是否有一种更有效的方法来获取从SFrame中的2列或更多列创建的组合列的唯一值?

pandas中,从2个或更多列中获取唯一值的高效方法是什么?

+0

输出中elems的顺序是否重要?将输出作为列表或数组可以吗? – Divakar

+0

[SFrame的API](https://turi.com/products/create/docs/generated/graphlab.SFrame.html)与Pandas API相比相当差,所以我不认为你可以做得更多与您的解决方案相比更有效率。也许该考虑使用[Apache Spark](http://spark.apache.org/)了? – MaxU

回答

2

我没有SFrame但pd.DataFrame测试:

sf[["x", "y"]].stack().value_counts().index.tolist() 
    [2, 1, 8, 7, 6, 5, 4] 
+0

快速问题,在这种情况下,在执行'.value_counts()'之前,一列(带有重复项)被附加到另一列(带有重复项)? – alvas

+0

是的,代码将数据堆栈,以便访问基础值。 – Merlin

+0

它的作品,我upvoted。但我认为一个答案会更合适。希望你不介意=) – alvas

1

虽然我不知道该怎么做,在SFrame,这里的@梅林的回答更详细的解释:

>>> import pandas as pd 
>>> df = pd.DataFrame({'x':[1,1,2,5,7], 'y':[2,4,6,8,2], 'z':[2,5,8,6,2]}) 
>>> df[['x', 'y']] 
    x y 
0 1 2 
1 1 4 
2 2 6 
3 5 8 
4 7 2 

为了仅提取列X和Y

>>> df[['x', 'y']] # Extract only columns x and y 
    x y 
0 1 2 
1 1 4 
2 2 6 
3 5 8 
4 7 2 

要堆叠每行2列到1个共lumn排,同时仍然能够访问他们的字典:

>>> df[['x', 'y']].stack()      
0 x 1 
    y 2 
1 x 1 
    y 4 
2 x 2 
    y 6 
3 x 5 
    y 8 
4 x 7 
    y 2 
dtype: int64 
>>> df[['x', 'y']].stack()[0]  
x 1 
y 2 
dtype: int64 
>>> df[['x', 'y']].stack()[0]['x'] 
1 
>>> df[['x', 'y']].stack()[0]['y'] 
2 

计数合并列中的所有元素的各个值:

>>> df[['x', 'y']].stack().value_counts() # index(i.e. keys)=elements, Value=counts 
2 3 
1 2 
8 1 
7 1 
6 1 
5 1 
4 1 

要访问索引和计数:

>>> df[['x', 'y']].stack().value_counts().index  
Int64Index([2, 1, 8, 7, 6, 5, 4], dtype='int64') 
>>> df[['x', 'y']].stack().value_counts().values 
array([3, 2, 1, 1, 1, 1, 1]) 

转换到一个列表:

>>> sf[["x", "y"]].stack().value_counts().index.tolist() 
[2, 1, 8, 7, 6, 5, 4] 

仍然SFrame的答案也会很好。相同的语法不适用于SFrame。

+0

IIUC,'stack()'很可能会复制底层数据 - 可能是你想避免的东西。 – ptrj

2

我能想到的最简单的方法是将转换为numpy的阵列,然后找到独特的价值

np.unique(sf[['x', 'y']].to_numpy()) 

array([1, 2, 4, 5, 6, 7, 8]) 

如果你需要它在sframe

SFrame({'xy_unique': np.unique(sf[['x', 'y']].to_numpy())}) 

enter image description here

2

SFrame

我没有使用SFrame,也不知道它在哪些条件下复制数据。 (是否选择sf['x']append将数据复制到内存?)。有pack_columnsstack方法SFrame,如果他们不复制数据,那么这应该工作:

sf[['x', 'y']].pack_columns(new_column_name='N').stack('N').unique() 

大熊猫

如果您的数据加载到内存中,然后你也许可以做到这一点的大熊猫有效无需额外复制。

# copies the data to memory 
df = sf[['x', 'y']].to_dataframe() 

# a reference to the underlying numpy array (no copy) 
vals = df.values 

# 1d array: 
# (numpy.ravel doesn't copy if it doesn't have to - it depends on the data layout) 
if np.isfortran(vals): 
    vals_1d = vals.ravel(order='F') 
else: 
    vals_1d = vals.ravel(order='C') 

uniques = pd.unique(vals_1d) 

大熊猫,因为它不排序的unique比numpy的的np.unique更有效。

2

看看this answer到类似的问题。请注意,Pandas的pd.unique函数比Numpy的函数快得多。

>>> pd.unique(sf[['x','y']].values.ravel()) 
array([2, 8, 5, 4, 1, 7, 6], dtype=object) 
1

这里有三种可行的方法之间的一个小基准:

from sframe import SFrame 
import numpy as np 
import pandas as pd 
import timeit 

sf = SFrame({'x': [1, 1, 2, 5, 7], 'y': [2, 4, 6, 8, 2], 'z': [2, 5, 8, 6, 2]}) 


def f1(sf): 
    return sf['x'].unique().append(sf['y'].unique()).unique() 


def f2(sf): 
    return sf['x'].append(sf['y']).unique() 


def f3(sf): 
    return np.unique(sf[['x', 'y']].to_numpy()) 

N = 1000 

print timeit.timeit('f1(sf)', setup='from __main__ import f1, sf', number=N) 
print timeit.timeit('f2(sf)', setup='from __main__ import f2, sf', number=N) 
print timeit.timeit('f3(sf)', setup='from __main__ import f3, sf', number=N) 

# 13.3195129933 
# 4.66225642657 
# 3.65669089489 
# [Finished in 23.6s] 

使用基准Windows7上+ i7_2.6ghz python2.7.11 64

结论:我建议你使用np.unique,这是基本上是f3

相关问题