我有一个熊猫数据帧,df:
c1 c2
0 10 100
1 11 110
2 12 120
如何迭代此数据帧的行?对于每一行,我希望能够通过列的名称访问其元素(单元格中的值)。例如:
for row in df.rows:
print(row['c1'], row['c2'])
我发现了一个类似的问题,建议使用以下任一项:
for date, row in df.T.iteritems():
for row in df.iterrows():
但我不知道row对象是什么,以及如何使用它。
更新:cs95更新了他的答案,包括简单的numpy矢量化。你可以简单地参考他的答案。
cs95表明,Pandas矢量化在使用数据帧计算数据方面远远优于其他Pandas方法。
我想补充一点,如果您首先将数据帧转换为NumPy数组,然后使用矢量化,它甚至比Pandas数据帧矢量化更快(这包括将其转换回数据帧序列的时间)。
如果您将以下函数添加到cs95的基准代码中,这将变得非常明显:
def np_vectorization(df):
np_arr = df.to_numpy()
return pd.Series(np_arr[:,0] + np_arr[:,1], index=df.index)
def just_np_vectorization(df):
np_arr = df.to_numpy()
return np_arr[:,0] + np_arr[:,1]
除了这篇文章中的好答案,我将提出“分而治之”的方法,我写这个答案并不是为了废除其他好答案,而是为了用另一种对我有效的方法来实现它们。它有两个步骤,即拆分和合并熊猫数据帧:
分裂与征服的证明:
您不需要使用矢量化或任何其他方法将数据帧的类型转换为另一种类型您不需要将代码循环化,这通常需要额外的时间在我的例子中,iterrows()和itertples()在整个数据帧上都具有相同的性能根据您对切片索引的选择,您将能够以指数方式加快迭代。索引越高,迭代过程越快。
分裂与征服的缺点:
您不应该依赖于同一数据帧和不同切片的迭代过程。这意味着,如果你想从其他切片读取或写入,那么可能很难做到这一点。
===============分而治之=================
步骤1:分割/切片
在这一步中,我们将在整个数据帧上划分迭代。假设你要将一个CSV文件读入panda df,然后对其进行迭代。在这种情况下,我有5000000条记录,我要将其拆分为100000条记录。
注意:我需要重申,正如本页其他解决方案中解释的其他运行时分析一样,在df上搜索时,“记录数”与“运行时”成指数比例。基于我的数据基准,以下是结果:
Number of records | Iteration rate [per second]
========================================
100,000 | 500
500,000 | 200
1,000,000 | 50
5,000,000 | 20
第2步:合并
这将是一个简单的步骤,只需将所有写入的CSV文件合并到一个数据帧中,然后将其写入一个更大的CSV文件。
以下是示例代码:
# Step 1 (Splitting/Slicing)
import pandas as pd
df_all = pd.read_csv('C:/KtV.csv')
df_index = 100000
df_len = len(df)
for i in range(df_len // df_index + 1):
lower_bound = i * df_index
higher_bound = min(lower_bound + df_index, df_len)
# Splitting/slicing df (make sure to copy() otherwise it will be a view
df = df_all[lower_bound:higher_bound].copy()
'''
Write your iteration over the sliced df here
using iterrows() or intertuples() or ...
'''
# Writing into CSV files
df.to_csv('C:/KtV_prep_' + str(i) + '.csv')
# Step 2 (Merging)
filename = 'C:/KtV_prep_'
df = (pd.read_csv(f) for f in [filename + str(i) + '.csv' for i in range(ktv_len // ktv_index + 1)])
df_prep_all = pd.concat(df)
df_prep_all.to_csv('C:/KtV_prep_all.csv')
参考:
数据流迭代的有效方法
将CSV文件连接到一个Pandas数据帧中
有时,有用的模式是:
# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
print(row_dict)
结果是:
{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}
对于查看和修改值,我将使用iterrows()。在for循环中,通过使用元组解包(参见示例:i,row),我使用行仅查看值,并在需要修改值时使用i和loc方法。正如前面的回答所述,这里您不应该修改正在迭代的内容。
for i, row in df.iterrows():
df_column_A = df.loc[i, 'A']
if df_column_A == 'Old_Value':
df_column_A = 'New_value'
在这里,循环中的行是该行的副本,而不是它的视图。因此,您不应该编写类似于行['a']='New_Value'的内容,它不会修改DataFrame。但是,您可以使用i和loc并指定DataFrame来完成这项工作。
虽然iterrows()是一个很好的选项,但有时itertples()会快得多:
df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})
%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop
%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop