基于当前行上方或下方的第 n 行的条件 - Python

Posted

技术标签:

【中文标题】基于当前行上方或下方的第 n 行的条件 - Python【英文标题】:Condition based on nth row above or below current row - Python 【发布时间】:2016-06-07 18:12:21 【问题描述】:

我想复制类似于 Alteryx 中的“多行公式”工具的东西。我目前正在读取一个 csv 文件,如果同一测试列中另一行的值为 true,我希望能够在列表中设置一个值。

样本数据

**Country**
China
India
Brazil
Indonesia

当它遍历包含巴西的行时,应该将“Y”附加到新列表中,因为中国在上面两行。其余部分应附加“N”。

import pandas as pd

csv_in = pd.read_csv('C:/sample.csv')

kind = []                           

for row in csv_in['Country']:
    if ***two rows above this row*** == 'China':
        kind.append('Y')
    elif ***one row below this row*** == 'Canada':
        kind.append('Y')
    else:
        kind.append("N")

csv_in['Result'] = kind

我无法找到与此问题相关的任何具体内容。任何帮助将不胜感激!

编辑:我意识到除了我最初提出的要求之外,我还需要做更多的事情。

  for row in csv_in['Country']:
      if  'hina' in ***two rows above this row***:
          kind.append('Y')
      elif ***one row below this row***.startswith('Can'):
          kind.append('X')
      else:
          kind.append("N")

【问题讨论】:

它以某种方式读取笨拙地迭代像熊猫数据框这样的可索引结构,然后使用两种特殊情况的偏移量作为条件来构建元素明智的具有相同长度和隐式 1 对 1 映射之间的布尔序列两个“列表”中的位置。应该更清楚的是,根据数据帧“国家”列长度的长度一次性准备一个 Falsy 或“N”列表,并找到数据帧的特殊情况索引,并将偏移量分别设置为下方 2 行和上方 1 行为 True或'y'。 ...现在@root 已经给出了答案 ;-) 【参考方案1】:

使用shift 构建一个布尔数组,其中包含'Y' 值应出现的位置,然后使用numpy.where 创建列:

import numpy as np

y_cond = (csv_in.shift(2) == 'China') | (csv_in.shift(-1) == 'Canada')
csv_in['Result'] = np.where(y_cond, 'Y', 'N')

如果您的 DataFrame 中有多个列,则需要使用 csv_in['Country'].shift() 而不是上面代码中的较短表示法。

一些稍微扩展的样本数据的结果输出:

     Country Result
0      China      N
1      India      N
2     Brazil      Y
3  Indonesia      N
4     Bhutan      N
5     Mexico      Y
6     Canada      N
7       Peru      N
8   Honduras      N

编辑:

如果您想分配非二进制值,我会采取稍微不同的方法。

首先将结果初始化为'N'。对于每个条件,像以前一样创建一个布尔数组,并使用loc 分配所需的值。以相反的重要性顺序执行此操作,因为后续匹配将覆盖以前的匹配。

请注意,您可以使用 .str 访问器将字符串函数应用于列,如文档的 Working with Text Data 部分所述。

csv_in['Result'] = 'N'

x_cond = csv_in['Country'].shift(-1).str.startswith('Can').fillna(False)
csv_in.loc[x_cond, 'Result'] = 'X'

y_cond = csv_in['Country'].shift(2).str.contains('hina').fillna(False)
csv_in.loc[y_cond, 'Result'] = 'Y'

.fillna(False) 是必需的,因为loc 需要纯布尔值,而shift 引入了NaN 值。如果您真的想按重要性顺序编写条件,您可以在 loc 中执行类似 x_cond & (csv_in['Result'] == 'N') 的操作,尽管这可能会影响性能。

更新的输出:

     Country Result
0      China      N
1      India      N
2     Brazil      Y
3  Indonesia      N
4     Bhutan      N
5     Mexico      X
6     Canada      N
7       Peru      N
8   Honduras      N

【讨论】:

谢谢!这完全符合我的要求!但我是个白痴,如果我想让加拿大返回“X”怎么办。如果我想使用startswith() 或“in”怎么办。我收到此错误:'series object has no attribute startswith'。我更新了我笨拙的代码。很抱歉!

以上是关于基于当前行上方或下方的第 n 行的条件 - Python的主要内容,如果未能解决你的问题,请参考以下文章

如何让 grep 打印每个匹配行下方和上方的行? [复制]

4周第3次课 vim 进入编辑模式 命令模式

过去 30 天的平均值,不包括当前记录(混合日期和基于行的条件)

关于VIM,知道这些就够了

vim的使用

vi命令-模式转换