pandas数据框 - 减少初始值

时间:2015-08-17 21:51:05

标签: python r pandas dataframe reduce

我将部分R内容移至Python,因此我必须使用pandas.DataFrame s。我想要优化几件事。

假设我们有一张桌子

key value
abc 1
abc 2
abd 1

我们希望获得格式{key -> list[values]}的字典。这就是我现在如何完成这项工作的方法。

from pandas import DataFrame
from StringIO import StringIO


def get_dict(df):
    """
    :param df:
    :type df: DataFrame
    """
    def f(accum, row):
        """
        :param accum:
        :type accum: dict
        """
        key, value = row[1]
        return accum.setdefault(key, []).append(value) or accum
    return reduce(f, df.iterrows(), {})


table = StringIO("key\tvalue\nabc\t1\nabc\t2\nabd\t1")
parsed_table = [row.rstrip().split("\t") for row in table]
df = DataFrame(parsed_table[1:], columns=parsed_table[0])
result = get_dict(df)  # -> {'abc': ['1', '2'], 'abd': ['1']}

我不喜欢的两件事:

  1. 内置reduce使用标准Python迭代协议,这会破坏基于NumPy的数据结构(如DataFrame)的速度。我知道DataFrame.apply具有reduce模式,但它不会采用dict之类的起始值。
  2. (一个小缺点)我必须使用索引来从行中获取特定值。我希望我可以按R中的名称连续访问特定字段,即row$key而不是row[1][0]
  3. 提前谢谢

2 个答案:

答案 0 :(得分:1)

而不是get_dict你可以使用词典理解:

In [100]: {key:grp['value'].tolist() for key, grp in df.groupby('key')}
Out[100]: {'abc': ['1', '2'], 'abd': ['1']}

自动生成带有列表值的dict意味着您将离开快速NumPy数组的领域,并迫使Python生成需要Python循环来迭代数据的对象。当数据集很大时,那些Python循环可能比等效的NumPy / Pandas函数调用慢得多。因此,如果您关心速度,那么您的最终目标可能并不理想。

如果您想利用NumPy / Pandas执行快速(呃)计算,您必须将数据保存在NumPy数组或Pandas NDFrame中。

答案 1 :(得分:1)

一种选择是使用groupby并使用pandas系列申请结束:

In [2]: df
Out[2]:
   key  value
0  abc      1
1  abc      2
2  abd      1

In [3]: df.groupby("key").value.apply(list)
Out[3]:
key
abc    [1, 2]
abd       [1]
Name: value, dtype: object

In [4]: _3.ix['abc']
Out[4]: [1, 2]