Новый столбец и итерация по строкам - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь добавить новый столбец в мой существующий набор данных (pandas dataframe). Этот новый столбец содержит элементы, которые удовлетворяют заданному условию c (см. Код ниже). Я перебираю строки, но не могу изменить значение строки на основе условия (строки должны иметь значение row_value[0] = var2 или row_value[0] = varB).

for index, row in sample_dataset.iterrows():
            row_value = ['Missing']
            for var1, var2 in var3:
                if row[0].endswith(var1):
                    row_value[0] = var2
                    break
            for varA,varB in varC:
                if row[0].endswith(varA): 
                    row_value[0] = varB
                    break

Любая помощь будет принята с благодарностью , Спасибо

Пример:

Исходный набор данных:

Column
hello_world.a
goodmorning_world.b
bye_world.1
...

Списки:

var1=['1','2','3']
var2=['11','22','33']
var3=list(zip(var1, var2))

аналогично для varA, varB, varC:

varA=['a','b','c']
varB=['aa','bb','cc']
varC=list(zip(varA, varB))

Я хотел бы иметь что-то вроде этого:

Ожидаемый результат

Column                  New_column
hello_world.a               aa
goodmorning_world.b         bb
bye_world.1                 11
...

1 Ответ

1 голос
/ 05 апреля 2020

Итак, давайте go шаг за шагом пройдем ваш код, сначала давайте определим фрейм данных

import pandas as pd

# create dataframe with nans in the new column you want to fill
sample_dataset = pd.DataFrame({'Column':['hello_world.a','goodmorning_world.b','bye_world.1']})

# create new column which we will fill later 
sample_dataset['New_column'] = pd.Series(index = sample_dataset.index, dtype='object')

Обратите внимание, что важно указать тип нового столбца, потому что вы хотите достичь создание нового столбца со смешанными типами элементов, числами и строками, и только python «объекты» могут содержать смешанные типы.

Давайте распечатаем его, чтобы увидеть, как оно выглядит

print(sample_dataset)
Out:
                Column  New_column
0        hello_world.a         NaN
1  goodmorning_world.b         NaN
2          bye_world.1         NaN    

Теперь давайте перейдем к остальной части вашего кода:

# the other variables you defined 
var1=['1','2','3']
var2=['11','22','33']
var3=list(zip(var1, var2))
varA=['a','b','c']
varB=['aa','bb','cc']
varC=list(zip(varA, varB))

# your code
for index, row in sample_dataset.iterrows():
            row_value = ['Missing']
            for var1, var2 in var3:
                if row[0]. endswith(var1):
                    row_value[0] = var2
                    break
            for varA,varB in varC:
                if row[0].endswith(varA): 
                    row_value[0] = varB
                    break

Давайте проверим, что ваш код что-то сделал на фрейм данных

Out:
                Column  New_column
0        hello_world.a         NaN
1  goodmorning_world.b         NaN
2          bye_world.1         NaN

Кажется, ничего не изменилось, но что-то действительно изменилось, что является row_value. Если я пытаюсь распечатать его после запуска вашего кода, я получаю:

print(row_value)
Out:
['11']

Опять же, это самая поразительная ошибка, поскольку она показывает, что ваша проблема не только с pandas и фреймами данных, но и с программированием в целом , Если вы хотите изменить переменную, вам нужно получить доступ к этой переменной, здесь переменная, которую вы хотите изменить, это ваш фрейм данных, который называется sample_dataset, но вместо того, чтобы вызывать его, вы вызываете row_value в следующих строках:

row_value[0] = var2
row_value[0] = varB

Именно поэтому в конце вашего кода row_value больше не [[отсутствует]], а ['11'], поэтому вы что-то меняете, а не свой фрейм данных.

Так как обновить значения в новом столбце исходного кадра данных? Вот как вы должны это сделать:

# iterating through rows, this is correct
for index, row in sample_dataset.iterrows():

            # you don't need to define row_value, but you want to access the value of 'Column' in the current row
            value = row['Column']

            # you could just do "for var1, var2 in list(zip(var1, var2))" without defining var3, not a mistake but it makes the code more concise
            for var1, var2 in var3:

                # using .endswith() will raise an error when you try to apply it to numbers, an alternative that works for both numbers and string is to simply access the last element of the array with [-1]
                if value[-1] == var1:

                    # this is how you change an element in a dataframe, i.e. using .at[index, column]
                    # here we say that we want to change the element in the current index in the column 'New_colum' with var2 
                    sample_dataset.at[index,'New_column'] = var2
                    break

            for varA,varB in varC:

                # same story as before
                if value[-1] == varA: 

                    sample_dataset.at[index,'New_column'] = varB
                    break

Давайте снова напечатаем фрейм данных, чтобы проверить, работает ли он:

print(sample_dataset)
Out:
                Column New_column
0        hello_world.a         aa
1  goodmorning_world.b         bb
2          bye_world.1         11

Итак, на этот раз мы получили доступ к фрейму данных и изменили значения New_column успешно. Go хотя код и, если у вас есть сомнения, просто прокомментируйте, я могу объяснить это более подробно.

В качестве последнего замечания, если вам нужно просто взять последний символ в первой строке и дважды это в новой колонке, есть гораздо лучшие способы сделать это. Например:

for index, row in sample_dataset.iterrows():

            value = row['Column']

            sample_dataset.at[index, 'New_column'] = value[-1]*2 

Опять же, если мы распечатаем его, мы увидим, что для выполнения работы достаточно трех строк кода:

print(sample_dataset)
Out:
                Column New_column
0        hello_world.a         aa
1  goodmorning_world.b         bb
2          bye_world.1         11

Таким образом, вы этого не сделаете нужно определить varA, B, C и все остальные, и вам не нужны тормоза или вложенные циклы. Мы даже можем сжать код в одну строку, используя .apply ()

sample_dataset['New_column'] = sample_dataset.apply(lambda x: x['Column'][-1]*2, axis=1)

Это снова даст вам те же результаты, что и раньше, но если у вас возникли проблемы с кодом, это может быть то, что вы хотите оставьте на будущее, когда у вас будет немного больше уверенности.

Также обратите внимание, что последние два метода создадут все строковые элементы, поэтому даже последний элемент 11 будет строкой, а не float64. Это может быть то, чего вы хотите избежать, и в этом случае вы должны просто использовать свой код, но в целом смешивать типы в столбце не очень хорошо.

Редактировать

, если вы хотите извлечь часть строки, соответствующую указанному правилу c (в данном случае, все после последнего периода), вам нужно использовать регулярные выражения (или регулярное выражение ). Regex в python реализован в библиотеке re, что вам нужно сделать:

# import library
import re

# define a patter of interest, this specific pattern means 'everything from the end of the string until you find a period'
pattern = r"([^.]*$)"

# now you can extract the final part from each element in your dataframe using re.search
last_part = re.search(pattern, element).groups()[0]

Просто чтобы показать, что он делает, давайте возьмем поддельное значение типа 'hello_world.com' и применим регулярное выражение к нему:

print(re.search(pattern, 'hello_world.com').groups()[0])
Out:
com

Теперь вы хотите изменить значение кода [-1] с помощью re.search, поэтому

if value[-1] == var1:
if value[-1] == varB:

должно стать

if re.search(pattern, value).groups()[0] == var1:
if re.search(pattern, value).groups()[0] == varB:

Не забудьте добавить импорт для re и определить шаблон в начале вашего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...