Создание новой переменной с использованием информации из нескольких строк в кадре данных - PullRequest
0 голосов
/ 18 января 2019

У меня есть датафрейм, который выглядит так:

df = pd.DataFrame({"HouseholdNumber": [1, 1, 1, 1, 1, 2, 2], "TypeOfPerson": ["Son", "Daughter", "Daughter", "Parent", "Parent", "Daughter", "Parent"], "Age": [17, 10, 20, 52, 45, 22, 50]})
print(df)
   HouseholdNumber TypeOfPerson  Age
0                1          Son   17   
1                1     Daughter   10   
2                1     Daughter   20  
3                1       Parent   52     
4                1       Parent   45    
5                2     Daughter   22    
6                2       Parent   50      

и я хочу создать новую переменную, используя информацию из нескольких строк. Это проблема для меня, потому что у меня проблемы с использованием простого условия df.loc (или np.where). В частности, я хочу, чтобы новая переменная имела значение no в случае, если человек не является родителем или не имеет детей в возрастных группах, a, если у родителя есть ребенок в возрасте 18 лет или младше и b если у родителя есть ребенок от 19 до 25 лет. Если у родителей есть ребенок обеих возрастных групп, значение все равно должно быть a. Номер HouseholdNumber указывает разные семьи, поэтому для каждого домохозяйства должны применяться все условия. Итак, датафрейм должен выглядеть так:

   HouseholdNumber TypeOfPerson  Age Child
0                1          Son   17    no
1                1     Daughter   10    no
2                1     Daughter   20    no
3                1       Parent   52     a
4                1       Parent   45     a
5                2     Daughter   22    no
6                2       Parent   50     b 

код, который я пытаюсь это

df["Child"]=""
for i in df["HouseholdNumber"].unique():
    if (df.loc[df.TypeOfPerson.isin(["Son", "Daughter"]) & (df.Age <= 18)]):
       if (df.loc[(df.TypeOfPerson == "Parent")]):
           df["Child"] = "a"
    elif (df.loc[df.TypeOfPerson.isin(["Son", "Daughter"]) & ((df.Age >= 19) & (df.Age <= 26))]):
       df["Child"] = "b"
    else:
        df["Child"] = "no"

что дает мне ошибку The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). Я не совсем уверен, куда идти отсюда, я всегда получаю эту ошибку. Даже без ошибки я подозреваю, что мой код не даст желаемого результата.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Я бы использовал groupby для чего-то подобного, поскольку вы можете иметь дело с каждым домохозяйством одновременно

Пример (обратите внимание, что не все случаи обрабатываются)

import pandas as pd

# Create the dataframe
df = pd.DataFrame(data={
    "TypeOfPerson": ["Son", "Parent", "Daughter", "Son", "Parent", "Daughter", "Daughter", "Parent", "Son"],
    "HouseholdNumber": [1, 1, 1, 1, 2, 2, 2, 3, 3],
    "Age": [17,50,20,13,40,19,5, 50, 25]
})

# Add new column
df["Child"] = pd.Series()

# Group by household
households = df.groupby("HouseholdNumber")

# Iterate through groups
for household_number in households.groups:
    household = households.get_group(household_number)

    # Household offspring
    offspring = household.query("TypeOfPerson == 'Son' | TypeOfPerson == 'Daughter'")

    # Sons and daughters that are 18 or younger
    children = offspring.query("Age <= 18")

    # Sons and daughters that young adults (19 >= age <= 25)
    young_adults = household.query("Age >= 19 & Age <= 25")

    # Parents
    parents = household.query("TypeOfPerson == 'Parent'")

    # Change original data frame
    df.loc[offspring.index, "Child"] = "No"
    if children.shape[0]:
        df.loc[parents.index, "Child"] = "a" 
    elif young_adults.shape[0]:
         df.loc[parents.index, "Child"] = "b" 
0 голосов
/ 18 января 2019

Ошибка здесь в том, что вы обращаетесь к df.loc со списком индексов, например:

 df.loc[df.TypeOfPerson.isin(["Son", "Daughter"]) & (df.Age <= 18)]

вернет фрейм данных с несколькими строками. Поэтому, когда вы помещаете его за if, он спрашивает, как оценить этот фрейм данных как логическое значение, будет ли это any ячеек True или all ячеек True и т. Д.

Один из способов исправить ошибку - указать указанную операцию, или, в вашем случае, вы хотите узнать, есть ли в доме какие-либо дочерние элементы, вы можете просто проверить длину отрезанного кадра данных:

for i in df["HouseholdNumber"].unique():
    # you didn't use this i in your code
    ppl_in_house = (df.HouseholdNumber == i)
    is_child = df.TypeOfPerson.isin(["Son", "Daughter"])

    num_children = sum(ppl_in_house & is_child)

Конечно, это только один способ решить вашу проблему, а не лучший.

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