pandas 数据框 - 减少初始值
pandas data frame - reduce with initial value
我要将我的一些 R
内容移至 Python
,因此我必须使用 pandas.DataFrame
。有几件事我想优化。
假设我们有一个 table
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']}
有两点我不喜欢它:
- 事实上,内置
reduce
使用标准 Python 迭代协议,这会降低 DataFrame
等基于 NumPy 的数据结构的速度。我知道 DataFrame.apply
有一个 reduce
模式,但它不像 dict
那样采用起始值。
- (一个小缺点) 我必须使用索引从行中获取特定值的事实。我希望我可以像
R
那样按名称连续访问特定字段,即 row$key
而不是 row[1][0]
提前致谢
您可以使用字典理解代替 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 中。
一种选择是使用 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]
我要将我的一些 R
内容移至 Python
,因此我必须使用 pandas.DataFrame
。有几件事我想优化。
假设我们有一个 table
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']}
有两点我不喜欢它:
- 事实上,内置
reduce
使用标准 Python 迭代协议,这会降低DataFrame
等基于 NumPy 的数据结构的速度。我知道DataFrame.apply
有一个reduce
模式,但它不像dict
那样采用起始值。 - (一个小缺点) 我必须使用索引从行中获取特定值的事实。我希望我可以像
R
那样按名称连续访问特定字段,即row$key
而不是row[1][0]
提前致谢
您可以使用字典理解代替 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 中。
一种选择是使用 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]