通过从每一行的不同列中选择一个元素,从 Pandas DataFrame 创建一个系列

Posted

技术标签:

【中文标题】通过从每一行的不同列中选择一个元素,从 Pandas DataFrame 创建一个系列【英文标题】:Create a Series from a Pandas DataFrame by choosing an element from different columns on each row 【发布时间】:2013-09-06 13:01:35 【问题描述】:

我的目标是。

例如,我有以下DataFrame:

In [171]: pred[:10]
Out[171]: 
                     0  1  2
Timestamp                   
2010-12-21 00:00:00  0  0  1
2010-12-20 00:00:00  1  1  1
2010-12-17 00:00:00  1  1  1
2010-12-16 00:00:00  0  0  1
2010-12-15 00:00:00  1  1  1
2010-12-14 00:00:00  1  1  1
2010-12-13 00:00:00  0  0  1
2010-12-10 00:00:00  1  1  1
2010-12-09 00:00:00  1  1  1
2010-12-08 00:00:00  0  0  1

而且,我有以下系列:

In [172]: useProb[:10]
Out[172]: 
Timestamp
2010-12-21 00:00:00    1
2010-12-20 00:00:00    2
2010-12-17 00:00:00    1
2010-12-16 00:00:00    2
2010-12-15 00:00:00    2
2010-12-14 00:00:00    2
2010-12-13 00:00:00    0
2010-12-10 00:00:00    2
2010-12-09 00:00:00    2
2010-12-08 00:00:00    0

我想创建一个新系列 usePred,它从 pred 中获取值,根据 useProb 中的列信息返回以下内容:

In [172]: usePred[:10]
Out[172]: 
Timestamp
2010-12-21 00:00:00    0
2010-12-20 00:00:00    1
2010-12-17 00:00:00    1
2010-12-16 00:00:00    1
2010-12-15 00:00:00    1
2010-12-14 00:00:00    1
2010-12-13 00:00:00    0
2010-12-10 00:00:00    1
2010-12-09 00:00:00    1
2010-12-08 00:00:00    0

这最后一步是我失败的地方。我试过这样的事情:

usePred = pd.DataFrame(index = pred.index)
for row in usePred:
    usePred['PREDS'].ix[row] = pred.ix[row, useProb[row]]

而且,我试过了:

usePred['PREDS'] = pred.iloc[:,useProb]

我在 *** 上搜索了几个小时,但似乎无法解决问题。

【问题讨论】:

【参考方案1】:

一种解决方案可能是使用get dummies(应该更有效):

In [11]: (pd.get_dummies(useProb) * pred).sum(axis=1)
Out[11]:
Timestamp
2010-12-21 00:00:00    0
2010-12-20 00:00:00    1
2010-12-17 00:00:00    1
2010-12-16 00:00:00    1
2010-12-15 00:00:00    1
2010-12-14 00:00:00    1
2010-12-13 00:00:00    0
2010-12-10 00:00:00    1
2010-12-09 00:00:00    1
2010-12-08 00:00:00    0
dtype: float64

您可以使用带有几个 loc 的 apply:

In [21]: pred.apply(lambda row: row.loc[useProb.loc[row.name]], axis=1)
Out[21]:
Timestamp
2010-12-21 00:00:00    0
2010-12-20 00:00:00    1
2010-12-17 00:00:00    1
2010-12-16 00:00:00    1
2010-12-15 00:00:00    1
2010-12-14 00:00:00    1
2010-12-13 00:00:00    0
2010-12-10 00:00:00    1
2010-12-09 00:00:00    1
2010-12-08 00:00:00    0
dtype: int64

诀窍在于您可以通过 name 属性访问行索引。

【讨论】:

@Brian 添加了另一个更简洁的解决方案。【参考方案2】:

这是使用DataFrame.lookup 的另一种方法:

pred.lookup(row_labels=pred.index, 
            col_labels=pred.columns[useProb['0']])

这似乎正是您所需要的,除了必须注意提供 标签 的值。例如,如果pred.columns 是字符串,而useProb['0'] 值是整数,那么我们可以使用

pred.columns[useProb['0']]

以便传递给col_labels 参数的值是正确的标签值。


例如,

import io
import pandas as pd
content = io.BytesIO('''\
Timestamp  0  1  2
2010-12-21 00:00:00  0  0  1
2010-12-20 00:00:00  1  1  1
2010-12-17 00:00:00  1  1  1
2010-12-16 00:00:00  0  0  1
2010-12-15 00:00:00  1  1  1
2010-12-14 00:00:00  1  1  1
2010-12-13 00:00:00  0  0  1
2010-12-10 00:00:00  1  1  1
2010-12-09 00:00:00  1  1  1
2010-12-08 00:00:00  0  0  1''')
pred = pd.read_table(content, sep='\s2,', parse_dates=True, index_col=[0])

content = io.BytesIO('''\
Timestamp  0
2010-12-21 00:00:00    1
2010-12-20 00:00:00    2
2010-12-17 00:00:00    1
2010-12-16 00:00:00    2
2010-12-15 00:00:00    2
2010-12-14 00:00:00    2
2010-12-13 00:00:00    0
2010-12-10 00:00:00    2
2010-12-09 00:00:00    2
2010-12-08 00:00:00    0''')
useProb = pd.read_table(content, sep='\s2,', parse_dates=True, index_col=[0])
print(pd.Series(pred.lookup(row_labels=pred.index, 
                col_labels=pred.columns[useProb['0']]),
                index=pred.index))

产量

    Timestamp
2010-12-21    0
2010-12-20    1
2010-12-17    1
2010-12-16    1
2010-12-15    1
2010-12-14    1
2010-12-13    0
2010-12-10    1
2010-12-09    1
2010-12-08    0
dtype: int64

【讨论】:

以上是关于通过从每一行的不同列中选择一个元素,从 Pandas DataFrame 创建一个系列的主要内容,如果未能解决你的问题,请参考以下文章

选择总和列,然后从列中获取最小值

通过从每个集合中仅选择一个值来选择 k 个大小的子集

通过从两个不同的数组中随机选择键和值将两个数组组合成一个数组

在每一行中从多个不同的列中查找唯一值

PySpark 通过从十进制列中删除比例来写入 csv

通过从数组中选择来创建排列