逐行迭代熊猫,并修改特定的“;“细胞”;以python的方式
我是python新手,我有一个pandas数据框架,我想逐行迭代(比如其他语言中的2d数组)。 目标是这样的逻辑:(如果df是一个类似2d的数组) 要点是:我想将当前行的内容移动到第1列中的上一行,若当前行第2列为空,而当前行第1列为空 我将如何以python的方式实现这一点?(例如,不使用for循环进行迭代)。我看到了一些关于矢量化的东西,但我真的不知道它是如何工作的 或者将df转换为列表列表或数组更容易?文件很大,所以我想用一种快速的方法,从excel文件中读取,所以我只是使用pandas的read_excel将其导入df。试试这个(假设第1列是指索引0处的列,第2列是指索引1处的列):逐行迭代熊猫,并修改特定的“;“细胞”;以python的方式,python,pandas,dataframe,Python,Pandas,Dataframe,我是python新手,我有一个pandas数据框架,我想逐行迭代(比如其他语言中的2d数组)。 目标是这样的逻辑:(如果df是一个类似2d的数组) 要点是:我想将当前行的内容移动到第1列中的上一行,若当前行第2列为空,而当前行第1列为空 我将如何以python的方式实现这一点?(例如,不使用for循环进行迭代)。我看到了一些关于矢量化的东西,但我真的不知道它是如何工作的 或者将df转换为列表列表或数组更容易?文件很大,所以我想用一种快速的方法,从excel文件中读取,所以我只是使用pandas的
将熊猫作为pd导入
将numpy作为np导入
col1,col2=df.columns[0],df.columns[1]
掩码=(df.loc[:,col1]!=“”)和(df.loc[:,col2]=“”)
mask.iloc[0]=False#不环绕第一行(即使条件适用)
df.loc[mask.shift(-1,fill_value=False),col1]=df.loc[mask,col1]。值
这里的关键点是使用将布尔掩码向后移动一。这只使用pandas/numpy矢量化函数,因此它比使用普通的Pythonfor
循环进行迭代要好得多
一步一步
col1,col2=df.columns[0],df.columns[1]
]
True
,即第一列为非空,第二列为空:
mask=(df.loc[:,col1]!=“”)和(df.loc[:,col2]=“”)
mask.iloc[0]=False
在这里,我们手动将掩码的第一个元素设置为False
,因为即使第一行满足条件,我们也无法对其执行任何操作(没有要将第一列的值复制到的前一行)。(这对于没有环绕的Series.shift
来说不是问题,但当我们在步骤3中使用此掩码来选择要分配的值时,使用df.loc[mask,col1]。值
:如果mask.iloc[0]
是True
,我们将比目标多一个值。)
mask.shift(-1,fill_值=False)
由于我们将掩码向后移动1,最后一个元素不会被定义,因此我们使用fill\u value=False
将其设置为False
——我们不想修改最后一行
df.loc[mask.shift(-1,fill_value=False),col1]=df.loc[mask,col1]。值
在这里,我们必须使用右侧的.values
来获得原始的numpy值数组,因为如果我们将其作为系列
,pandas将尝试对齐lhs和rhs的索引(由于我们将行移动了一个,索引将不匹配,因此最终结果将包含NaN
s);相反,我们只想将rhs的第一个元素分配给lhs的第一个插槽,将第二个元素分配给第二个插槽,等等
>>sample=pd.DataFrame([(“spam”、“)、(“foo”、“bar”)、(“baz”、“)、(“eggs”))
>>>df=sample.copy()
>>>df
0 1
0垃圾邮件
1富吧
2巴兹
3个鸡蛋
>>>col1,col2=df.columns[0],df.columns[1]
>>>掩码=(df.loc[:,col1]!=“”)和(df.loc[:,col2]=“”)
>>>mask.iloc[0]=False
>>>df.loc[mask.shift(-1,fill_value=False),col1]=df.loc[mask,col1]。值
>>>df
0 1
0垃圾邮件
1巴兹酒吧
2巴兹
3个鸡蛋
补遗 如果您确实希望将第一行的值换行到最后一行(如果条件适用于第一行)-即,您希望循环移动值-,则可以使用而不是
系列。shift
:
mask=(df.loc[:,col1]!=“”)和(df.loc[:,col2]=“”)
df.loc[np.roll(掩码,-1),col1]=np.roll(df.loc[mask,col1]。值,-1)
然后,继续上一个示例:
df=sample.copy()
>>>掩码=(df.loc[:,col1]!=“”)和(df.loc[:,col2]=“”)
>>>df.loc[np.roll(掩码,-1),col1]=np.roll(df.loc[mask,col1]。值,-1)
>>>df
0 1
0垃圾邮件
1巴兹酒吧
2巴兹
3个垃圾鸡蛋
如果您找不到更具Python风格的方法,以下是正确的代码:
for i in range(1, len(df)):
if df.iloc[i, 2]='' and df.iloc[i, 1]!='':
df.iloc[i-1, 1]=df.iloc[i,1]
df.iloc[i, 1]=''
看看熊猫的方法。1) 使用shift获取列1的滞后版本(滞后列1)。2) 如果逻辑测试为真(第2列为空,第1列不为空),则用滞后列覆盖第1列。3) 删除lagged_col_1。当您遇到三个连续的行时,您会怎么做:1)所有行在col1中都有一个值,2)所有三行中的col2都为空?您当前的代码将只使用第二行替换第一行,而不使用第三行。这就是你想要的吗?@RichieV不,这确实是针对这些文件的,所以我不需要其他任何东西。他们有时会遇到这个问题,因为导出它们的程序出错(公立医院使用这个程序,所以在导出过程中不容易更改任何内容),所以我只需要一种快速的方法来修复它,因为文件很大,循环似乎很慢。正如我在阿纳坎德回答的评论中所说的那样,这样的速度大约快70倍。。。这几天我读了很多关于熊猫的书,这些东西看起来很神奇!哇,非常详细的回答!非常感谢,我会测试这些文件,然后回来
for i in range(1, len(df)):
if df.iloc[i, 2]='' and df.iloc[i, 1]!='':
df.iloc[i-1, 1]=df.iloc[i,1]
df.iloc[i, 1]=''