Python初学者在这里。
这是我的问题: 我有一个大约3200行和660列的csv文件。 这些行用0、1或50填充。
我需要根据以下要求更新新创建的列“ answer”:
因此,例如,行[1,0,0,0,1,1,1,50,0,0,0,1]在其末尾应具有新值'3',因为我们发现在找到50之前是三个1。
这是我的代码:
df_numRows = len(df.values)
df_numCols = len(df.columns)
for row in range(df_numRows):
df_sum = 0
for col in range(df_numCols):
if '50' not in df.values[row]:
df.at[row, 'answer'] = '0'
elif df.values[row][col] == '0':
continue
elif df.values[row][col] == '1':
df_sum += 1
df.at[row, 'answer'] = df_sum
elif df.values[row][col] == '50':
break
我写了这个嵌套的for循环来遍历我的Pandas数据框,但是运行似乎要花很长时间。
我在同一数据集上运行了这段代码,但是只有100行x 660列,它花费了大约1.5分钟,但是,当我尝试在整个事情上运行它时,它运行了大约2.5个小时,而我只是将其关闭,因为我认为它花了太长时间。
如何使我的代码更高效/更快/更好?我希望你们能提供任何帮助,如果这是一个简单的问题,我预先表示歉意,但是我才刚刚开始使用Python!
谢谢大家!
答案 0 :(得分:3)
找到50后只需执行cumprod
,如果为50,则下面的所有值都将变为0,然后使用此布尔数据帧过滤原始df,然后执行sum
df=pd.DataFrame({'A':[1, 0, 0, 0, 1, 1, 50, 0, 0, 0, 1] })
df.mul(df.ne(50).cumprod()).sum()
Out[35]:
A 3
dtype: int64
答案 1 :(得分:1)
df = pd.DataFrame([
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1], # No 50s
[1, 0, 0, 0, 1, 1, 50, 0, 0, 0, 1], # One 50
[1, 50, 0, 0, 1, 50, 50, 0, 0, 0, 1], # Three 50s but 2 are consecutive
[1, 50, 0, 0, 1, 1, 50, 0, 0, 0, 1], # Two 50s
])
df
0 1 2 3 4 5 6 7 8 9 10
0 1 0 0 0 1 1 0 0 0 0 1
1 1 0 0 0 1 1 50 0 0 0 1
2 1 50 0 0 1 50 50 0 0 0 1
3 1 50 0 0 1 1 50 0 0 0 1
logical_and
和accumulate
方法一起使用 np.logical_and
将使用and
运算符并将其应用于一组布尔值。 accumulate
部分说要继续应用它,并在我们进行操作时跟踪所有先前布尔值中最新的and
。通过指定axis=1
,我想对每一行进行此操作。这将返回一个布尔数组,其中的行为true,直到我们达到50
的值为止。然后,我检查是否有all(1)
有五十个。适当的乘法运算得出所有值的总和,而不是每行前50 ...之前的50。
d = np.logical_and.accumulate(df.ne(50), axis=1)
df.mul(d).mul(~d.all(1), 0).sum(1)
0 0
1 3
2 1
3 1
dtype: int64
合并以获取新列
d = np.logical_and.accumulate(df.ne(50), axis=1)
df.assign(answer=df.mul(d).mul(~d.all(1), 0).sum(1))
0 1 2 3 4 5 6 7 8 9 10 asnswer
0 1 0 0 0 1 1 0 0 0 0 1 0
1 1 0 0 0 1 1 50 0 0 0 1 3
2 1 50 0 0 1 50 50 0 0 0 1 1
3 1 50 0 0 1 1 50 0 0 0 1 1
如果你想全力以赴的脾气暴躁
v = df.values
a = np.logical_and.accumulate(v != 50, axis=1)
df.assign(answer=(v * (a & ~a.all(1, keepdims=True))).sum(1))
0 1 2 3 4 5 6 7 8 9 10 asnswer
0 1 0 0 0 1 1 0 0 0 0 1 0
1 1 0 0 0 1 1 50 0 0 0 1 3
2 1 50 0 0 1 50 50 0 0 0 1 1
3 1 50 0 0 1 1 50 0 0 0 1 1
答案 2 :(得分:0)
请尝试这种逻辑,让我知道是否有帮助。
df_numRows = len(df.values)
df_numCols = len(df.columns)
for row in range(df_numRows):
df_sum = 0
try:
indexOf50 = np.argwhere(df.loc[row]==50)[0][0]
colArrayTill50 = df.loc[row][:indexOf50].values
numberOfOne = colArrayTill50.sum()
except:
numberOfOne = 0
print(numberOfOne)
答案 3 :(得分:0)
这可以解决它,尽管有点健壮:
String result = obj.methodToTest("string_not_valid_for_my_obj");
assertEquals("An exception has been thrown", result);