R到Python:使用Shift和ifelse

时间:2017-10-25 14:18:26

标签: python r dataframe

示例数据:

test = structure(list(A = 1:16, B = c(".", NA, NA, NA, ".", NA, NA, 
NA, ".", NA, NA, NA, ".", NA, NA, NA), C = c(6L, NA, NA, NA, 
6L, NA, NA, NA, 6L, NA, NA, NA, 6L, NA, NA, NA), D = c(58, 59, 
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), E = c(0.945252, 
0.949158, 0.945252, 0.945252, 0.945252, 0.945252, 0.945252, 0.949158, 
0.949158, 0.949158, 0.949158, 0.945252, 0.945252, 0.945252, 0.945252, 
0.945252), F = c(62.4375, NA, 62.34375, NA, 62.28125, NA, 62.28125, 
NA, 62.25, NA, 62.21875, NA, 62.25, NA, 62.28125, NA)), .Names = c("A", 
"B", "C", "D", "E", "F"), row.names = c(NA, 16L), class = "data.frame")

我在R中有上面的数据框。我想用一些逻辑替换NA值。

R我写道:

test2 = test

library(data.table)

for(m in 1:length(test2)){test2[,m] = ifelse(is.na(test2[,m]), 
                                             ifelse(is.na(shift(test2[,m]))==F, shift(test2[,m]),
                                                    ifelse(is.na(shift(test2[,m], n=2))==F, shift(test2[,m], n=2),
                                                           ifelse(is.na(shift(test2[,m], n=3))==F, shift(test2[,m], n=3),
                                                                  ifelse(is.na(shift(test2[,m], n=4))==F, shift(test2[,m], n=4),
                                                                         shift(test2[,m], n=5)))))
                                             , test2[,m])}

这实现了我想要的。但是现在,我所做的一切都是从R转换为Python。除了这个问题,我已设法翻译我的所有工作。

我写了等价物:

import numpy as np
import pandas as pd

for m in range(0, len(test2.columns)):
    if test2.iloc[:,m].isnull():
        if  test2.iloc[:,m].shift(periods=1).notnull():
            test2.iloc[:,m] = test2.iloc[:,m].shift(periods=1)
        else:
            if test2.iloc[:,m].shift(periods=2).notnull():
                 test2.iloc[:,m] = test2.iloc[:,m].shift(periods=2)
            else:
                if test2.iloc[:,m].shift(periods=3).notnull():
                     test2.iloc[:,m] = test2.iloc[:,m].shift(periods=3)
                else:
                    if test2.iloc[:,m].shift(periods=4).notnull():
                         test2.iloc[:,m] = test2.iloc[:,m].shift(periods=4)
                    else:
                         test2.iloc[:,m] = test2.iloc[:,m].shift(periods=5)

我意识到这在Python中不起作用甚至没有意义,因为Rifelse使用shift时会将逻辑应用于每一行,而在Python我相信我会问这个系列是True还是False。为了速度,我真的不想遍历整个数据框,这就是shiftR中如此之大的原因。我猜可能有一种简单的方法可以使用If中的ilocPython,但我{a} Python noob。

enter image description here

enter image description here

CSV:

 A  B   C   D   E   F
1   .   6   58  0.945252    62.4375
2           59  0.949158    
3           0   0.945252    62.34375
4           1   0.945252    
5   .   6   2   0.945252    62.28125
6           3   0.945252    
7           4   0.945252    62.28125
8           5   0.949158    
9   .   6   6   0.949158    62.25
10          7   0.949158    
11          8   0.949158    62.21875
12          9   0.945252    
13  .   6   10  0.945252    62.25
14          11  0.945252    
15          12  0.945252    62.28125
16          13  0.945252    

2 个答案:

答案 0 :(得分:1)

在python中证明这很容易。一旦你认识到我的问题基本上是一个归责问题,我想用最后的观察结果,我相信它变得如此简单:

test2 = test.fillna(method = 'pad')

R中为未来找到了一种更简单的方法

library(zoo)
test2 = na.locf(test)

答案 1 :(得分:1)

您可以使用DataFrame.ffill,它比调用fillna稍短。

test = test.ffill()

它的作用是使用每行中第一个后续的非空值向前填充所有NaN。或者,您可以使用fillna调用method='ffill'来执行相同的操作:

test = test.fillna(method='ffill')

method='pad'完全相同。