#python #pandas #for-loop
Вопрос:
У меня есть следующий код, но он немного повторяющийся. Может ли кто-нибудь, пожалуйста, сказать мне, как поместить эти утверждения в цикл. Фрейм данных состоит из столбцов от T1 до T12 и от P1 до P12. Здесь я показал только 3 состояния для каждого условия.
У меня есть следующий код, но он немного повторяющийся. Может ли кто-нибудь, пожалуйста, сказать мне, как поместить эти утверждения в цикл. Фрейм данных состоит из столбцов от T1 до T12 и от P1 до P12. Здесь я показал только 3 состояния для каждого условия.
первое условие
df['P1'] = df.apply(lambda row: 1 if row['P1'] >= 5 * row['T1'] else 0, axis=1)
df['P2'] = df.apply(lambda row: 1 if row['P2'] >= 5 * row['T2'] else 0, axis=1)
df['P3'] = df.apply(lambda row: 1 if row['P3'] >= 5 * row['T3'] else 0, axis=1)
второе условие
df['T1'] = df.apply(lambda row: 1 if row['T1'] >= 7 else 0, axis=1)
df['T2'] = df.apply(lambda row: 1 if row['T2'] >= 7 else 0, axis=1)
df['T3'] = df.apply(lambda row: 1 if row['T3'] >= 7 else 0, axis=1)
третье условие
df['G1'] = np.where((df['T1']==1) amp; (df['P1'] ==1), 1, 0)
df['G2'] = np.where((df['T2']==1) amp; (df['P2'] ==1), 1, 0)
df['G3'] = np.where((df['T3']==1) amp; (df['P3'] ==1), 1, 0)
Ответ №1:
При попытке свернуть код в циклы, посмотрите, что меняется и как это происходит. Вот ваши первые три заявления:
df['P1'] = df.apply(lambda row: 1 if row['P1'] >= 5 * row['T1'] else 0, axis=1)
df['P2'] = df.apply(lambda row: 1 if row['P2'] >= 5 * row['T2'] else 0, axis=1)
df['P3'] = df.apply(lambda row: 1 if row['P3'] >= 5 * row['T3'] else 0, axis=1)
Давайте на мгновение упростим это:
df['P1'] = func("P1", "T1")
df["P2"] = func("P2", "T2")
Я удалил все, что не меняется. Что делают эти строковые параметры, которые каждый раз увеличиваются на 1. Так что мы можем свернуть его вот так:
for i in range(1,4): # integer between 1 and 3, not 4!
p = f"p{i}"
t = f"t{i}"
print("p", p, "t", t)
Действительно запустите этот код! Вы видите, как он создает необходимые нам параметры? Так что теперь мы дома и обсохли:
for i in range(1, 3):
p = f"p{1}"
t = f"t{1}"
df[p] = df.apply(lambda row: 1 if row[p] >= 5 * row[t] else 0, axis=1)
Все ваши другие условия могут быть свернуты аналогичным образом.
В этом случае, как отмечается в другом ответе, можно неявно записать этот цикл в панд. (Т. е. для векторизации: действительно ли это запускает цикл или правильно векторизовано, я не знаю, потому что я не смотрел, как реализована pandas.) Но все равно стоит понять, как это сделать явно.
Ответ №2:
Не используйте циклы apply
, потому что здесь существуют векторизованные более быстрые альтернативы — сравните все отфильтрованные строки и приведите True, False
к 1,0
, преобразовав маску в целые числа:
np.random.seed(2021)
df = pd.DataFrame(np.random.randint(10, size=(5, 9)))
df.columns = ['P1','P2','P3','T1','T2','T3','G1','G2','G3']
print (df)
P1 P2 P3 T1 T2 T3 G1 G2 G3
0 4 5 9 0 6 5 8 6 6
1 6 6 1 5 7 1 1 5 2
2 0 3 1 0 2 6 4 8 5
3 1 6 7 5 6 9 5 6 9
4 2 4 3 9 2 8 5 3 1
#for filter all columns starting by P, T, G
p = df.filter(regex='^P').columns
t = df.filter(regex='^T').columns
g = df.filter(regex='^G').columns
#for filter all columns by lists
p = ['P1','P2','P3']
t = ['T1','T2','T3']
g = ['G1','G2','G3']
df[p] = (df[p] >= 5 * df[t].to_numpy()).astype(int)
df[t] = (df[t] >= 7).astype(int)
df[g] = ((df[t] == 1) amp; (df[p].to_numpy() == 1)).astype(int)
print (df)
P1 P2 P3 T1 T2 T3 G1 G2 G3
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 1 0 0 0 0
2 1 0 0 0 0 0 0 0 0
3 0 0 0 0 0 1 0 0 0
4 0 0 0 1 0 1 0 0 0
Ответ №3:
Я думаю, ты можешь попробовать это..
indexP = ['P1','P2','P3']
indexT = ['T1','T2','T3']
indexG = ['G1','G2','G3']
for x in indexP :
df[x] = (df[x] >= 5 * df[x])
for y in indexT :
df[y] = (df[y] >= 7)
for z in indexG
df[z] = ((df[z]==1) amp; (df[z] ==1))