如何在 Pandas 中选择行范围?
Posted
技术标签:
【中文标题】如何在 Pandas 中选择行范围?【英文标题】:How to select range of rows in Pandas? 【发布时间】:2018-09-27 00:10:23 【问题描述】:我创建了一个具有一系列特征的数据框。我想创建一个新列来选择两个特定行之间的所有行(这将是输入)。
说dataframe如下:
data = 'currency': ['Euro', 'Euro', 'Euro', 'Dollar', 'Dollar', 'Yen',
'Yen', 'Yen', 'Pound', 'Pound', 'Pound, 'Pesos',
'Pesos'],
'cost': [34, 67, 32, 29, 48, 123, 23, 45, 78, 86, 23, 45, 67]
df = pd.DataFrame(data, columns = ['currency', 'cost'])
df
df 表:
我想添加一个在满足条件时分配 1 的新列。就我而言,条件是两种特定货币之间的所有行。例如,假设我想要“美元”和“英镑”之间的所有货币。我的猜测是我必须创建一个掩码并将其用作条件,即选择第一个“美元”行和最后一个“英镑”行之间的所有行(即第 3-10 行)。
我在创建该掩码时遇到了问题,因为货币是按字母顺序选择的:
mask = (df['currency'] >= 'Dollar') & (df['currency'] <= 'Pound')
上面创建了一个新列,其中包含所有货币的 T,但“日元”除外。我可以看到为什么上述方法失败了,但想不出一种方法来做我想做的事。
注意:相同的货币名称将分组出现,例如“磅”不能在第 4-5 行和第 8-10 行中。
【问题讨论】:
能否请您添加预期的输出。 很好的问题。只是对您的快速和理解反应表示一点赞赏! 【参考方案1】:也适用于重复索引的通用解决方案:
a = df['currency'].eq('Dollar').cumsum()
b = df['currency'].eq('Pound').iloc[::-1].cumsum()
df['new'] = a.mul(b).clip_upper(1)
唯一索引的替代方法:
a = df['currency'].eq('Dollar').idxmax()
b = df['currency'].eq('Pound').iloc[::-1].idxmax()
df['new'] = 0
df.loc[a:b, 'new'] = 1
print (df)
currency cost new
0 Euro 34 0
1 Euro 67 0
2 Euro 32 0
3 Dollar 29 1
4 Dollar 48 1
5 Yen 123 1
6 Yen 23 1
7 Yen 45 1
8 Pound 78 1
9 Pound 86 1
10 Pound 23 1
11 Pesos 45 0
12 Pesos 67 0
解释:
-
先比较
Series.eq
与==
相同的地方
获取cumsum
[::-1]
的第二个条件反向掩码
将mul
相乘并将非0
替换为1
为clip_upper
第二个解决方案使用idxmax
作为第一个索引值并通过loc
设置1
【讨论】:
【参考方案2】:在逻辑或上使用 Numpy 的累加
cumor = np.logical_or.accumulate
c = df.currency.values
d = c == 'Dollar'
p = c == 'Pound'
df.assign(new=(cumor(d) & cumor(p[::-1])[::-1]).astype(np.uint))
currency cost new
0 Euro 34 0
1 Euro 67 0
2 Euro 32 0
3 Dollar 29 1
4 Dollar 48 1
5 Yen 123 1
6 Yen 23 1
7 Yen 45 1
8 Pound 78 1
9 Pound 86 1
10 Pound 23 1
11 Pesos 45 0
12 Pesos 67 0
【讨论】:
以上是关于如何在 Pandas 中选择行范围?的主要内容,如果未能解决你的问题,请参考以下文章
如何创建一个新的 pandas 列,该列是索引范围中每个值的列表,不包括行值
从表中随机选择行 - Python Pandas 读取 SQL