我有这种格式的数据框:
a b x
1 1 31
1 2 1
1 3 42
1 4 423
1 5 42
1 6 3
1 7 44
1 8 65437
1 9 73
2 1 5656
2 2 7
2 3 5
2 4 5
2 5 34
a
和b
是索引,x
是值。
我希望获得行1 9 73
和2 5 34
,换句话说,就是该级别的最后一行。
我一直在弄.loc
,.iloc
和.xs
一小时,但我无法让它发挥作用。我该怎么做?
答案 0 :(得分:3)
print (df.groupby('a', as_index=False).last())
a b x
0 1 9 73
1 2 5 34
如果a
和b
的级别为MultiIndex
,请先致电reset_index
:
print (df.reset_index().groupby('a', as_index=False).last())
a b x
0 1 9 73
1 2 5 34
答案 1 :(得分:2)
以#include <stdlib.h>
#include <stdio.h>
struct Product//declaring a structure
{
char code[25];
//variables inside a structure
char name[25];
double price;
int quantity;
};
int main(void) {
struct Product product;
int add;
FILE *fptr;
FILE *nfptr;
printf("-------------------------------\n");
printf(" ADD ITEM\n");
printf("-------------------------------\n");
printf("1.GST Items\n");
printf("2.Non-GST Items\n");
scanf("%d", &add);
switch (add) //start of switch statement
{
case 1:
fptr = fopen("gst.txt", "wr"); //open file
if (fptr == NULL)//checking whether the file is empty or not
{
printf("File cannot be found\n");
}
else //else statement
{
printf("Add Item Code:\n");
scanf("%s", product.code);
printf("Item name:\n");
scanf("%s", product.name);
printf("Item price:\n");
scanf("%.2lf", &product.price);
printf("Item quantity:\n");
scanf("%d", &product.quantity);
fprintf(fptr, "%s;%s;%.2f;%d\n", product.code, product.name, product.price, product.quantity);
fclose(fptr);
}//end else statement
break;
case 2:
nfptr = fopen("ngst.txt", "r"); //open file
if (nfptr == NULL)//checking whether the file is empty or not
{
printf("File cannot be found\n");
}
else //else statement
{
printf("Add Item Code:\n");
scanf("%s", product.code);
printf("Item name:\n");
scanf("%s", product.name);
printf("Item price:\n");
scanf("%.2lf", &product.price);
printf("Item quantity:\n");
scanf("%d", &product.quantity);
fprintf(nfptr, "%s;%s;%.2f;%d\n", product.code, product.name, product.price, product.quantity);
fclose(nfptr);
}//end else statement
break;
}
}
作为数据框并且列df
已经排序,这是一种方法 -
a
基本思想是我们沿着排序列df[np.append(np.diff(df['a'])>0,True)]
执行区分,并使用a
查找正变化,为我们提供一个布尔数组。布尔数组中的(>0)
元素将表示该列中“组”的结尾。因为,最后一个组的最后一个元素没有变化,所以我们需要在末尾附加一个true
元素到该布尔数组。最后,使用这样一个布尔数组索引True
以从中选择行并为我们提供所需的输出。
可以使用np.unique
使用其可选参数df
建议另一种方法,该方法将为我们提供每个组的第一个出现元素的索引。因此,要使其适用于最后一个元素,只需翻转列return_index
,使用a
并获取第一个出现的索引,然后从np.unique
中的总行数中减去它们。最后,使用最终输出的索引到df
。因此,实施将是 -
df
示例运行 -
df.iloc[df.shape[0] - np.unique(df['a'][::-1],return_index=True)[1] - 1]
答案 2 :(得分:1)
jezrael提出的groupby
解决方案是高级的通用解决方案。但是,当groupby
生成许多不同的组时(在OP给出的示例中,这可能是由a
的许多不同值引起的),它的性能非常差。在这里,我为特殊情况(与OP的情况相匹配)提出了一种优化的解决方案。
假设您有一个由MultiIndex
索引的数据帧,该数据帧具有多个级别,并且这些级别的 last 的值始终在每个组中以相同的值开始;例如,假设值始终从1
开始并递增。在下面的示例中,这将是number
级别。
value
name number
a 1 0.548126
b 1 0.774775
2 0.483701
3 0.820758
c 1 0.696832
2 0.905071
d 1 0.750546
2 0.761081
e 1 0.944682
2 0.336210
然后,要获得number
的每个唯一值(或具有其他任何级别的值的组合)的最大/最后一个name
值的行的横截面,可以执行以下操作:
df[np.roll(df.index.get_level_values('number') == 1, -1)]
您会得到:
value
name number
a 1 0.548126
b 3 0.820758
c 2 0.905071
d 2 0.761081
e 2 0.336210
一个接一个:
df.index.get_level_values('number')
:获取每一行number
级别的值的数组df.index.get_level_values('number') == 1
:对于True
为1的那些行,布尔数组为number
。np.roll(df.index.get_level_values('number') == 1, -1)
:以循环方式将前一个数组的所有值向后移一个位置(即第一个元素变为最后一个,第二个元素变为第一个,依此类推)。想法是,组的 last 值始终紧接在组的 first 值之前,该值始终为1
。因此,如果我们为number
值为1的行获得布尔掩码,则可以将所有这些布尔 backwards 移位一个,最后得到一个掩码值number
。
考虑到最后一行的特殊情况,可以通过循环移位 来进行考虑,这样第一个布尔值最终会落在最后—第一行的number
始终等于{{1} },因此布尔值将始终为1
,因此总是(如预期的那样)选择最后一行。
True
def innermost_level_max(df, start_value=1, drop_level=False):
assert df.index.is_lexsorted()
level_values = df.index.get_level_values(-1)
result = df[np.roll(level_values == start_value, -1)]
if drop_level:
result = result.droplevel(-1)
return result
这允许您创建一个示例数据框:
import itertools as itt
import numpy as np
import pandas as pd
import perfplot
rng = np.random.default_rng(42)
def generate_names():
alphabet = [chr(i) for i in range(ord('a'), ord('z') + 1)]
for length in itt.count(1):
for tup in itt.product(*([alphabet]*length)):
yield ''.join(tup)
def make_ragged_df(n):
lengths = rng.integers(1, 3, endpoint=True, size=n)
names = np.fromiter(
itt.chain.from_iterable(itt.repeat(n, times=r) for n, r in zip(generate_names(), lengths)),
dtype='U100',
count=n
)
numbers = np.fromiter(itt.chain.from_iterable(map(range, lengths)), int, count=n) + 1
index = pd.MultiIndex.from_arrays([names, numbers], names=['name', 'number'])
data = np.random.rand(n)
df = pd.DataFrame({'value': data}, index=index)
return df
使用>>> make_ragged_df(10)
value
name number
a 1 0.548126
b 1 0.774775
2 0.483701
3 0.820758
c 1 0.696832
2 0.905071
d 1 0.750546
2 0.761081
e 1 0.944682
2 0.336210
:
perfplot
如果您知道import perfplot
benchmarks = perfplot.bench(
setup=lambda n: make_ragged_df(n),
kernels=[
lambda df: df.groupby('name', sort=False).tail(1),
lambda df: df[np.roll(df.index.get_level_values('number') == 1, -1)],
],
labels=["with groupby", "with np.roll on == 1"],
n_range=range(50, 10000, 500),
xlabel="total number of rows",
)
benchmarks.show()
始终的最后一个值是什么,例如3,您只需要索引切片就可以了:
number
或横截面:
df.loc[pd.IndexSlice[:, 3], :]
但是如果是这种情况,那么您一开始就不会读这个问题。