我有一个看起来像这样的数据框:
Numbers Names
0 A
1 A
2 B
3 B
4 C
5 C
6 C
8 D
10 D
如果两个名称的“名称”列中的值都相同,则我的数字(整数)必须是连续的:例如,在6到8之间,数字不是连续的,但这很好,因为列“名称”从C更改为D。但是,在8到10之间,这是一个问题,因为两行具有相同的值“名称”,但不是连续的。
我想编写一个代码,返回根据上述逻辑需要添加的缺少数字。
import itertools as it
import pandas as pd
df = pd.read_excel("booki.xlsx")
c1 = df['Numbers'].copy()
c2 = df['Names'].copy()
for i in it.chain(range(1,len(c2)-1), range(1,len(c1)-1)):
b = c2[i]
c = c2[i+1]
x = c1[i]
n = c1[i+1]
if c == b and n - x > 1:
print(x+1)
它将打印丢失但重复两次的数字,因此对于示例中的数据框,它将打印:
9
9
但我只想打印:
9
也许逻辑上有些失败?
谢谢
答案 0 :(得分:1)
您可以使用groupby('Names')
,然后使用shift
获取每个组中以下元素之间的差异,然后仅选择没有-1
作为差异的元素,然后打印他们的以下号码。
尝试一下:
import pandas as pd
import numpy as np
from io import StringIO
df = pd.read_csv(StringIO("""
Numbers Names
0 A
1 A
2 B
3 B
4 C
5 C
6 C
8 D
10 D"""), sep="\s+")
differences = df.groupby('Names', as_index=False).apply(lambda g: g['Numbers'] - g['Numbers'].shift(-1)).fillna(-1).reset_index()
missing_numbers = (df[differences != -1]['Numbers'].dropna()+1).tolist()
print(missing_numbers)
输出:
[9.0]
答案 1 :(得分:0)
我不确定这里是否需要itertools
。这是仅使用熊猫方法的一种解决方案。
groupby
根据Names
列对数据进行分组Numbers
列中选择min
和max
merge
和子数据框一起使用此值isna
reset_index
代码在这里:
df = pd.DataFrame({"Numbers": [0, 1, 2, 3, 4, 5, 6, 8, 10, 15],
"Names": ["A", "A", "B", "B", "C", "C", "C", "D", "D", "D"]})
def select_missing(df):
# Select min and max values
min_ = df.Numbers.min()
max_ = df.Numbers.max()
# Create integer range
serie = pd.DataFrame({"Numbers": [i for i in range(min_, max_ + 1)]})
# Merge with df
m = serie.merge(df, on=['Numbers'], how='left')
# Return rows not matching the equality
return m[m.isna().any(axis=1)]
# Group the data per Names and apply "select_missing" function
out = df.groupby("Names").apply(select_missing)
print(out)
# Numbers Names
# Names
# D 1 9 NaN
# 3 11 NaN
# 4 12 NaN
# 5 13 NaN
# 6 14 NaN
out = out[["Numbers"]].reset_index(level=0)
print(out)
# Names Numbers
# 1 D 9
# 3 D 11
# 4 D 12
# 5 D 13
# 6 D 14