Как использовать цикл для столбцов в фрейме данных в Python

#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))