Pandas数据框架 - 初始值缩减

5
我正在将一些关于 R 的内容迁移到 Python,因此我必须使用 pandas.DataFrame。有几件事情我想要进行优化。
假设我们有一个表格。
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迭代协议,导致像DataFrame这样的基于NumPy的数据结构速度变慢。我知道DataFrame.apply有一个reduce模式,但它没有像dict那样带一个起始值。
  2. (一个小缺点)我必须使用索引才能从行中获取特定的值。我希望我可以像在R中一样通过名称访问行中的特定字段,即row$key而不是row[1][0]

提前谢谢

2个回答

1

你可以使用字典推导式来替换 get_dict

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

自动产生一个值为列表的字典意味着您正在离开快速NumPy数组的领域,并迫使Python生成需要通过Python循环迭代数据的对象。当数据集很大时,这些Python循环可能比等效的NumPy/Pandas函数调用慢得多。因此,如果您关心速度,则最终目标可能不理想。
如果您想利用NumPy/Pandas进行快速计算,您必须将数据保留在NumPy数组或Pandas NDFrame中。

我并不是非常关注速度,而是尽可能避免在可提高的地方失去速度。你能推荐任何用来替换字典的NumPy数据结构吗?我一直在R中使用“列表”来处理这种情况,但那是另外一个故事了。我选择了dict -> list组合进行快速键搜索和快速追加,这不需要重新分配整个数组。我不知道是否存在任何基于哈希的NumPy结构和/或动态数组。还是应该单独提出这个问题? - Eli Korvigo
1
这取决于你接下来想做什么,或者你的最终目标是什么。 你可能应该跳过形成这个字典,保留DataFrame,并找出哪些基于Pandas的方法可以直接帮助你实现最终目标。 例如,如果你计划聚合列表中的值,那么df.groupy('key').agg(...)可能是你要寻找的。 - unutbu
我刚刚看了你编辑过的评论。也许你应该提出一个单独的问题,并将所有细节都详细说明。 - unutbu
虽然我非常喜欢你写的那个简洁的代码行,但是我接受了Randy的答案,因为它更符合标题的要求。我希望我能给你两次赞。非常感谢你。 - Eli Korvigo

1

一种选择是使用groupby和apply,以结束一个pandas Series:

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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接