12

给定一个来自 的矩阵SFrame

>>> 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]

我想获得xandy列的唯一值,我可以这样做:

>>> 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 个或更多列创建的组合列的唯一值?

从 2 列或更多列中获取唯一值的有效方法在 pandas 中的等效性是什么pandas

4

6 回答 6

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())})

在此处输入图像描述

于 2016-08-19T17:12:04.657 回答
2

框架

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

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

熊猫

如果您的数据适合内存,那么您可以在 pandas 中有效地执行此操作,而无需额外的副本。

# 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)

pandasunique比 numpy 更有效,np.unique因为它不排序。

于 2016-08-19T17:12:47.390 回答
2

看看这个对类似问题的回答。请注意,Pandas 的pd.unique功能比 Numpy 的要快得多。

>>> pd.unique(sf[['x','y']].values.ravel())
array([2, 8, 5, 4, 1, 7, 6], dtype=object)
于 2016-08-22T05:27:51.783 回答
2

我没有 SFrame,但在 pd.DataFrame 上进行了测试:

  sf[["x", "y"]].stack().value_counts().index.tolist()
  [2, 1, 8, 7, 6, 5, 4]
于 2016-08-03T04:46:54.710 回答
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 x64 进行基准测试

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

于 2016-08-25T20:18:00.933 回答
1

虽然我不知道如何在 SFrame 中做到这一点,但这里有一个对@Merlin 答案的更长解释:

>>> 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 列行,同时仍然能够将它们作为字典进行访问:

>>> 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。

于 2016-08-03T05:27:10.233 回答