在不使用for循环的情况下将值应用于DataFrame

时间:2019-05-23 12:24:12

标签: python pandas dataframe

我正在寻找一种将值应用于DataFrame中的列的更快的方法。该值基于第一列和第二列中的两个True and False值。这是我目前的解决方案:

df['result'] = df.check1.astype(int)

for i in range(len(df)):
    if df.result[i] != 1:
        df.result[i] = df.result.shift(1)[i] + df.check2[i].astype(int)

产生以下结果:

    check1  check2  result
0   True    False   1
1   False   False   1
2   False   False   1
3   False   False   1
4   False   False   1
5   False   False   1
6   False   True    2
7   False   False   2
8   False   True    3
9   False   False   3
10  False   True    4
11  False   False   4
12  False   True    5
13  False   False   5
14  False   True    6
15  False   False   6
16  False   True    7
17  False   False   7
18  False   False   7
19  False   False   7
20  False   True    8
21  False   False   8
22  False   True    9
23  True    False   1
24  False   False   1

因此,第三列必须是一个数字,该数字基于其上方一行中的值。 如果check1为True,则数字应返回到1。如果check2为true,则需要在数字上添加1。否则,数字保持不变。

当前代码很好,但是花了我太长的时间,因为我需要将此代码应用于大约为70.000行。我很确定它可以改善(我猜是使用apply函数,但不确定)。
有什么想法吗?

2 个答案:

答案 0 :(得分:3)

使用pandas.DataFrame.groupby.cumsum

import pandas as pd

df['result'] = df.groupby(df['check1'].cumsum())[['check1', 'check2']].cumsum().sum(1)

或@Dan的建议:

df['result'] = df.groupby(df['check1'].cumsum())['check2'].cumsum().add(1)

输出:

    check1  check2  result
0     True   False     1.0
1    False   False     1.0
2    False   False     1.0
3    False   False     1.0
4    False   False     1.0
5    False   False     1.0
6    False    True     2.0
7    False   False     2.0
8    False    True     3.0
9    False   False     3.0
10   False    True     4.0
11   False   False     4.0
12   False    True     5.0
13   False   False     5.0
14   False    True     6.0
15   False   False     6.0
16   False    True     7.0
17   False   False     7.0
18   False   False     7.0
19   False   False     7.0
20   False    True     8.0
21   False   False     8.0
22   False    True     9.0
23    True   False     1.0
24   False   False     1.0

答案 1 :(得分:0)

您要使用上一行的值来迭代数据帧。在这种情况下,最有效的方法是直接迭代基础的numpy数组:

df = pd.read_fwf(io.StringIO(t))

df['result'] = df.check1.astype(int)

res = df['result'].values
c1 = df['check1'].values
c2 = df['check2'].values
old = -1
for i in range(len(df)):
    if res[i] != 1:
        res[i] = old + int(c2[i])
    old = res[i]

这很好用,因为numpy数组是可变类型,所以更改反映在数据框中。

Timeit表示,这是@Chris的原始解决方案的两倍,但在@Dan进行改进后仍快1.5倍。